@stacksjs/defaults 0.75.390 → 0.75.398
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.
- package/ai/skills/stacks-actions/SKILL.md +1 -1
- package/ai/skills/stacks-ai/SKILL.md +62 -0
- package/ai/skills/stacks-buddy/SKILL.md +1 -0
- package/ai/skills/stacks-composables/BROWSER.md +8 -0
- package/ai/skills/stacks-desktop/SKILL.md +85 -0
- package/ai/skills/stacks-native/CATALOG.md +16 -16
- package/ai/skills/stacks-security/SKILL.md +26 -0
- package/ai/skills/stacks-security-audit/SKILL.md +4 -0
- package/ai/skills/stacks-stx/SKILL.md +2 -1
- package/app/Actions/AI/CompleteAction.ts +50 -0
- package/app/Actions/AI/complete-action.test.ts +20 -0
- package/app/Actions/AI/complete-request.test.ts +91 -0
- package/app/Actions/AI/complete-request.ts +119 -0
- package/ide/vscode/package.json +1 -1
- package/package.json +4 -4
- package/resources/components/Dashboard/Auth/AuthCard.stx +10 -3
- package/resources/components/Dashboard/Auth/ForgotPassword.stx +3 -1
- package/resources/components/Dashboard/Auth/ForgotPasswordDashboard.stx +5 -0
- package/resources/components/Dashboard/Auth/Login.stx +3 -1
- package/resources/components/Dashboard/Auth/LoginDashboard.stx +5 -0
- package/resources/components/Dashboard/Auth/Register.stx +3 -1
- package/resources/components/Dashboard/Auth/RegisterDashboard.stx +5 -0
- package/resources/components/Dashboard/Auth/ResetPassword.stx +3 -1
- package/resources/components/Dashboard/Auth/ResetPasswordDashboard.stx +5 -0
- package/routes/dashboard.ts +2 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stacks-actions
|
|
3
|
-
description: Use when working with Stacks server actions - creating actions in app/Actions/, auto-generated API actions from the useApi model trait, the
|
|
3
|
+
description: Use when working with Stacks server actions - creating actions in app/Actions/, auto-generated API actions from the useApi model trait, the 675 default framework actions (auth, dashboard, commerce, content, deployment, jobs), action request/response handling, or action registration. Covers @stacksjs/actions and storage/framework/defaults/app/Actions/.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
6
|
allowed-tools: Read Edit Write Bash Grep Glob
|
|
@@ -22,6 +22,7 @@ ai/src/
|
|
|
22
22
|
│ ├── openai/index.ts # GPT + image + transcription + TTS
|
|
23
23
|
│ ├── ollama/index.ts # Local LLM driver
|
|
24
24
|
│ └── bedrock/ # Amazon Bedrock, through the Converse API
|
|
25
|
+
├── complete.ts # complete()/completeStream(): inline ghost-text completions
|
|
25
26
|
├── image.ts # Image generation & vision
|
|
26
27
|
├── speech.ts # Provider-neutral text-to-speech & speech-to-text
|
|
27
28
|
├── search.ts # RAG, embeddings, vector index
|
|
@@ -341,6 +342,66 @@ const sessionId = driver.getLastSessionId()
|
|
|
341
342
|
await driver.resumeSession(sessionId, 'Add validation')
|
|
342
343
|
```
|
|
343
344
|
|
|
345
|
+
## Inline completions (ghost text)
|
|
346
|
+
|
|
347
|
+
`complete()` is the continuation at the cursor, for editors that show grey text
|
|
348
|
+
after the caret and accept it with Tab. It uses the app's configured default
|
|
349
|
+
driver (any of the four) and that driver's fast model class, asks for ONLY the
|
|
350
|
+
continuation, and cleans the answer: the echoed prefix, the model's markup,
|
|
351
|
+
chatter and refusals (to `''`), everything past the first sentence or line, and
|
|
352
|
+
anything that runs into the text after the cursor.
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { complete, completeStream } from '@stacksjs/ai'
|
|
356
|
+
|
|
357
|
+
const { completion } = await complete({
|
|
358
|
+
before: 'Remember to buy milk, eggs and ', // the last 2000 chars are sent
|
|
359
|
+
after: '', // the first 500 chars are sent
|
|
360
|
+
kind: 'todo', // 'note' | 'prompt' | 'todo' | 'text'
|
|
361
|
+
context: 'Groceries', // note title, library description
|
|
362
|
+
maxTokens: 48, // default 48
|
|
363
|
+
signal: controller.signal, // abort: rejects with an AbortError
|
|
364
|
+
driver: 'bedrock', // default: ai.completion.driver, then ai.default
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
for await (const { completion } of completeStream({ before })) paint(completion) // the whole suggestion so far
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
- `{ completion: '' }` is "no suggestion", never an error: nothing to continue,
|
|
371
|
+
`ai.completion.enabled: false`, no driver configured, or the model declined. A
|
|
372
|
+
real driver failure throws.
|
|
373
|
+
- The model is, in order: `input.model`, `ai.completion.model`, a Haiku (Anthropic,
|
|
374
|
+
Bedrock) or Nova Micro/Lite found in `ai.models`, then the fast defaults in
|
|
375
|
+
`models.ts` (`DEFAULT_ANTHROPIC_FAST_MODEL`, `DEFAULT_BEDROCK_FAST_MODEL`); on
|
|
376
|
+
OpenAI and Ollama it is the driver's configured model. Bedrock Claude needs the
|
|
377
|
+
account's Anthropic use-case form submitted, otherwise list a Nova model in
|
|
378
|
+
`ai.models` (or set `ai.completion.model`) and completions use that.
|
|
379
|
+
- A small LRU keyed on the tail of `before` (plus kind, model and the head of
|
|
380
|
+
`after`) makes retyping free; `completionCache.clear()` empties it.
|
|
381
|
+
- Requests carry `maxRetries: 0` and the abort `signal` reaches the HTTP drivers
|
|
382
|
+
(Bedrock rejects at once and drops the late response), and each reports
|
|
383
|
+
`recordUsage` with `metadata: { feature: 'completion', kind }`, so `onUsage`
|
|
384
|
+
can price them separately. `ChatCompletionOptions` gained `signal`,
|
|
385
|
+
`maxRetries` and `usageMetadata` for this; Ollama now honours `maxTokens`
|
|
386
|
+
(`num_predict`) and reports usage like the other drivers.
|
|
387
|
+
- `completionStatus(config)` says whether a driver can answer, without a call;
|
|
388
|
+
`postProcessCompletion(raw, { before, after, kind })` is the cleanup, reusable
|
|
389
|
+
with your own model call.
|
|
390
|
+
|
|
391
|
+
`POST /ai/complete` (default `Actions/AI/CompleteAction`, in the guarded `/ai`
|
|
392
|
+
route group of the dashboard bundle) takes `{ before, after?, kind?, context? }`
|
|
393
|
+
and answers `{ completion }`: 401 when signed out, 422 for a bad body, a 90 per
|
|
394
|
+
minute per-user rate limit (429), `''` when no driver is configured, 502 when the
|
|
395
|
+
provider fails. To mount it elsewhere, one line in `routes/api.ts`:
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
route.post('/complete', 'Actions/AI/CompleteAction').middleware('auth') // POST /api/complete
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
The client half is `useCompletion()` and `<AiTextarea>` in stx
|
|
402
|
+
(`stacks-stx`, `stacks-composables/BROWSER.md`): `<AiTextarea kind="note" fetcher="/api/complete" v-model:value="body" />`.
|
|
403
|
+
Tests: `core/ai/tests/complete.test.ts`, `defaults/app/Actions/AI/complete-request.test.ts`.
|
|
404
|
+
|
|
344
405
|
## config/ai.ts
|
|
345
406
|
|
|
346
407
|
```typescript
|
|
@@ -352,6 +413,7 @@ await driver.resumeSession(sessionId, 'Add validation')
|
|
|
352
413
|
anthropic: { model: 'claude-sonnet-5-5' },
|
|
353
414
|
bedrock: { model: 'global.anthropic.claude-sonnet-5-5' },
|
|
354
415
|
},
|
|
416
|
+
completion: { enabled: true, maxTokens: 48 }, // optional: driver, model for inline completions
|
|
355
417
|
}
|
|
356
418
|
```
|
|
357
419
|
|
|
@@ -129,6 +129,7 @@ buddy dev -i/--interactive # interactive server selection menu
|
|
|
129
129
|
buddy dev -l/--with-localhost # include localhost URL in output
|
|
130
130
|
buddy dev --browser # open the browser app instead of a configured native window
|
|
131
131
|
buddy dev --site # open the marketing site instead of the detected app entry
|
|
132
|
+
buddy dev --detach # outlive the shell: nohup ./buddy dev --frontend --detach &
|
|
132
133
|
buddy dev -p/--project [name]
|
|
133
134
|
buddy dev --verbose
|
|
134
135
|
```
|
|
@@ -23,6 +23,14 @@ implementation rather than a newer docs list. Demand legacy helpers commonly
|
|
|
23
23
|
expose getters, `get()`, `subscribe()`, and `stop()`. Their getters are not
|
|
24
24
|
automatically signal-tracked template values.
|
|
25
25
|
|
|
26
|
+
STX 0.2.762 adds demand-delivered `useCompletion` for inline ghost text:
|
|
27
|
+
`useCompletion({ fetch: (ctx, signal) => Promise<string>, debounceMs = 250, minChars = 12, enabled })`
|
|
28
|
+
returns signals `ghost` and `pending` (plus `error`) and `update(before, after, caret, meta?)`,
|
|
29
|
+
`accept()`, `acceptWord()`, `dismiss()`, `destroy()`. It debounces, aborts the previous request,
|
|
30
|
+
discards stale answers, asks nothing during IME composition, a selection (`meta.selecting`), mid-word
|
|
31
|
+
or below `minChars`, and typing the start of a suggestion consumes it. `<AiTextarea>` from
|
|
32
|
+
`@stacksjs/components` is the textarea built on it (`kind`, `context`, `fetcher` URL or function).
|
|
33
|
+
|
|
26
34
|
STX 0.2.628 adds demand-delivered `useAnimationFrame` for canvas and simulations.
|
|
27
35
|
Imported TypeScript controllers use an explicit
|
|
28
36
|
`import { useAnimationFrame } from '@stacksjs/stx/composables'` and declare
|
|
@@ -252,9 +252,94 @@ Two things that bite, both silently:
|
|
|
252
252
|
`buddy build:dmg` warns when a finished bundle contains more than one
|
|
253
253
|
Bun-compiled executable, naming them and what the repetition costs.
|
|
254
254
|
|
|
255
|
+
## Native macOS apps (`config/desktop.ts`)
|
|
256
|
+
|
|
257
|
+
A project whose app is a client of an HTTP API (a hosted service, not a local server) declares it in
|
|
258
|
+
`config/desktop.ts`, the way `config/mobile.ts` declares a phone app, and `buddy build:desktop` builds a
|
|
259
|
+
native AppKit app from its stx screens: no web view, no launcher.
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import type { DesktopConfig } from '@stacksjs/types'
|
|
263
|
+
|
|
264
|
+
export default {
|
|
265
|
+
macos: {
|
|
266
|
+
appName: 'Library',
|
|
267
|
+
bundleId: 'com.example.library',
|
|
268
|
+
teamId: '3JJRNQW6B7', // not a secret
|
|
269
|
+
url: process.env.LIBRARY_API_URL || 'http://127.0.0.1:3408',
|
|
270
|
+
nativeScreens: ['Main', 'Settings'], // resources/native/<name>.stx
|
|
271
|
+
shareStorage: { auth_token: 'auth.token' },
|
|
272
|
+
window: { width: 1180, height: 760, minWidth: 860, minHeight: 540 },
|
|
273
|
+
icon: 'resources/native/icon/AppIcon-1024.png',
|
|
274
|
+
privacy: { tracking: false, collectedDataTypes: [] },
|
|
275
|
+
},
|
|
276
|
+
} satisfies DesktopConfig
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
- `buddy build:desktop` compiles the screens (`compileNativeBundle`), builds Craft's AppKit host
|
|
280
|
+
(`craft-native/macos`, cached per Craft revision), lays out `<App>.app` and signs it ad hoc. `buddy dev:desktop`
|
|
281
|
+
does the same and opens it. Output: `storage/framework/desktop/macos/`.
|
|
282
|
+
- The toolchain is not the app's business: Craft resolves the pinned Zig through Pantry and fetches and builds the pinned
|
|
283
|
+
zig-js into `~/.cache/craft/toolchain` (`CRAFT_TOOLCHAIN_DIR` moves it, `CRAFT_ZIG` overrides the compiler).
|
|
284
|
+
- The host reads `Contents/Resources/craft-app.json` (written by the build) when Finder launches it, so the app has no
|
|
285
|
+
arguments. The API origin is `url`, and `craft.secureStorage` is the Keychain (`craft.session` is the `auth.token` item).
|
|
286
|
+
- `buddy desktop:apple:package` and `publish` build the same bundle for the Mac App Store (sandbox, network client,
|
|
287
|
+
application identifier, Keychain group, embedded profile). Name, bundle id, team, version, category and icon come
|
|
288
|
+
from `config/desktop.ts`; only the credentials (identities, profile, API key) are Apple variables. `--universal` is not
|
|
289
|
+
supported for native apps yet.
|
|
290
|
+
- A `macos` section in `config/desktop.ts` switches `build:desktop` and `dev:desktop` to this path; without one they
|
|
291
|
+
build the Craft web-view app as before.
|
|
292
|
+
- One set of views can be both: the web server resolves the native primitives (`View`, `Text`, `ScrollView`, ...) as
|
|
293
|
+
components of last resort (stx config `nativePrimitives`), so `resources/views` pages written with them are also native
|
|
294
|
+
screens. Menus, windows and the Keychain are the screen's `craft.desktop` and `craft.secureStorage`.
|
|
295
|
+
|
|
296
|
+
### An app that runs its own API (`macos.agent`)
|
|
297
|
+
|
|
298
|
+
A local-first app (a browser, an inbox, anything whose data is this Mac) runs the project's routes inside the
|
|
299
|
+
app instead of talking to a hosted server. `buddy new <name> --desktop` scaffolds one (combinable with
|
|
300
|
+
`--minimal`, and happy to scaffold into a directory that holds only `.git`):
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
export default {
|
|
304
|
+
macos: {
|
|
305
|
+
appName: 'Browser',
|
|
306
|
+
bundleId: 'com.example.browser',
|
|
307
|
+
agent: true, // or { port, entry, appRoutes, staticDir }
|
|
308
|
+
nativeScreens: ['Main'],
|
|
309
|
+
webkit: true, // link WebKit into the host, for <WebView>
|
|
310
|
+
defaultBrowser: true, // http/https URL types, HTML/XHTML/webarchive/PDF document types
|
|
311
|
+
permissions: { camera: true, microphone: 'For calls in web pages.', location: true, downloads: true, printing: true },
|
|
312
|
+
dockMenu: [{ title: 'New Window', action: 'new-window' }],
|
|
313
|
+
},
|
|
314
|
+
} satisfies DesktopConfig
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
- The agent (`@stacksjs/desktop-build` `startDesktopAgent`, `src/agent.ts`) is `Bun.serve` on 127.0.0.1, on the
|
|
318
|
+
port remembered in `~/Library/Application Support/<App>/agent.port` (any free port when it is taken). The host fetches
|
|
319
|
+
`GET /native/session` and gets an HttpOnly, SameSite=Strict cookie holding a token minted for this launch; every other
|
|
320
|
+
request needs that cookie and a Host header of `127.0.0.1:<port>` or `localhost:<port>`, so a DNS-rebinding page
|
|
321
|
+
cannot call it. `url` is not needed.
|
|
322
|
+
- It serves the app's routes in process: `routes/` as `app/Routes.ts` mounts them, plus the agent's own module
|
|
323
|
+
(`app/Desktop/Agent.ts` by convention, `agent.entry` otherwise). Routes the agent module adds are not prefixed. A
|
|
324
|
+
default-exported `(request) => Response` there replaces the router entirely.
|
|
325
|
+
- `buddy dev:desktop` runs the launcher from source in the project (`bun`, no bundle), which boots the routes as
|
|
326
|
+
`buddy dev:api` does. `buddy build:desktop` compiles the launcher into `<App>.app/Contents/MacOS/<App>`, with the host
|
|
327
|
+
beside it as `craft-runtime` and `desktop-agent.json` in Resources. A compiled binary cannot import route files off
|
|
328
|
+
disk (the router refuses), so the build imports the registry's route files, the agent module and every
|
|
329
|
+
`'Actions/...'` they name statically (`provideActions`); what they import travels inside the app.
|
|
330
|
+
- The launcher (`src/agent-launcher.ts`) holds a single-instance lock (`agent.pid`), logs to
|
|
331
|
+
`~/Library/Logs/<App>.log` when launched without a terminal, and quits with the window.
|
|
332
|
+
- Entitlements: the Bun executable gets `allow-jit`, `allow-unsigned-executable-memory` and
|
|
333
|
+
`disable-library-validation`; in the sandbox the agent adds `network.server`, and the host is signed with only
|
|
334
|
+
`app-sandbox` and `inherit`. `permissions` adds each device entitlement and its `NS*UsageDescription` (an explicit
|
|
335
|
+
`usageDescriptions` entry wins).
|
|
336
|
+
- `webkit` needs a craft-native whose `buildMacOSNative` takes `webkit`; the build checks Craft's source and fails by
|
|
337
|
+
name rather than building a host with blank web views. `dockMenu` reaches the host through `craft-app.json`.
|
|
338
|
+
|
|
255
339
|
## CLI Commands
|
|
256
340
|
|
|
257
341
|
```bash
|
|
342
|
+
buddy new <name> --desktop # a Stacks app that is also a native Mac app, API inside (macos.agent)
|
|
258
343
|
buddy dev:desktop # start the desktop development server
|
|
259
344
|
buddy build:desktop # build the launcher + Craft runtime payload
|
|
260
345
|
buddy desktop:apple:init # generate the reusable GitHub Actions caller
|
|
@@ -11,8 +11,8 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
11
11
|
| Package | Task guidance | Source entry | Retained tests |
|
|
12
12
|
|---|---|---|---|
|
|
13
13
|
| `@stacksjs/action-runner` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/action-runner/src/index.ts) | 1 |
|
|
14
|
-
| `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) |
|
|
15
|
-
| `@stacksjs/ai` | [`stacks-ai`](../stacks-ai/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/index.ts) |
|
|
14
|
+
| `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) | 95 |
|
|
15
|
+
| `@stacksjs/ai` | [`stacks-ai`](../stacks-ai/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/index.ts) | 21 |
|
|
16
16
|
| `@stacksjs/alias` | [`stacks-alias`](../stacks-alias/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/alias/src/index.ts) | 1 |
|
|
17
17
|
| `@stacksjs/analytics` | [`stacks-analytics`](../stacks-analytics/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/index.ts) | 6 |
|
|
18
18
|
| `@stacksjs/api` | [`stacks-api`](../stacks-api/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/api/src/index.ts) | 9 |
|
|
@@ -21,7 +21,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
21
21
|
| `@stacksjs/auth` | [`stacks-auth`](../stacks-auth/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/index.ts) | 124 |
|
|
22
22
|
| `@stacksjs/browser` | [`stacks-browser`](../stacks-browser/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/index.ts) | 8 |
|
|
23
23
|
| `@stacksjs/browser-extension` | [`stacks-browser-extension`](../stacks-browser-extension/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser-extension/src/index.ts) | 7 |
|
|
24
|
-
| `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) |
|
|
24
|
+
| `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 176 |
|
|
25
25
|
| `@stacksjs/build` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/build/src/index.ts) | 4 |
|
|
26
26
|
| `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) | 18 |
|
|
27
27
|
| `@stacksjs/calendar-api` | [`stacks-calendar`](../stacks-calendar/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/calendar-api/src/index.ts) | 2 |
|
|
@@ -39,7 +39,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
39
39
|
| `@stacksjs/datetime` | [`stacks-datetime`](../stacks-datetime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/index.ts) | 13 |
|
|
40
40
|
| `@stacksjs/defaults` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/defaults/package.json) | 2 |
|
|
41
41
|
| `@stacksjs/deploy` | [`stacks-deploy`](../stacks-deploy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/deploy/package.json) | 1 |
|
|
42
|
-
| `@stacksjs/desktop-build` | [`stacks-desktop`](../stacks-desktop/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/index.ts) |
|
|
42
|
+
| `@stacksjs/desktop-build` | [`stacks-desktop`](../stacks-desktop/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/index.ts) | 15 |
|
|
43
43
|
| `@stacksjs/development` | [`stacks-development`](../stacks-development/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/development/package.json) | 1 |
|
|
44
44
|
| `@stacksjs/dns` | [`stacks-dns`](../stacks-dns/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/index.ts) | 3 |
|
|
45
45
|
| `@stacksjs/docs` | [`stacks-docs`](../stacks-docs/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/docs/src/index.ts) | 2 |
|
|
@@ -78,7 +78,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
78
78
|
| `@stacksjs/router` | [`stacks-router`](../stacks-router/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/index.ts) | 99 |
|
|
79
79
|
| `@stacksjs/scheduler` | [`stacks-scheduler`](../stacks-scheduler/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/index.ts) | 15 |
|
|
80
80
|
| `@stacksjs/search-engine` | [`stacks-search-engine`](../stacks-search-engine/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/search-engine/src/index.ts) | 11 |
|
|
81
|
-
| `@stacksjs/security` | [`stacks-security`](../stacks-security/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/index.ts) |
|
|
81
|
+
| `@stacksjs/security` | [`stacks-security`](../stacks-security/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/index.ts) | 12 |
|
|
82
82
|
| `@stacksjs/server` | [`stacks-server`](../stacks-server/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/server/src/index.ts) | 28 |
|
|
83
83
|
| `@stacksjs/shell` | [`stacks-shell`](../stacks-shell/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/shell/src/index.ts) | 1 |
|
|
84
84
|
| `@stacksjs/sites` | [`stacks-sites`](../stacks-sites/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/sites/src/index.ts) | 3 |
|
|
@@ -115,11 +115,11 @@ Evidence directory: [1 retained tests](https://github.com/stacksjs/stacks/blob/m
|
|
|
115
115
|
|
|
116
116
|
Guidance: [`stacks-actions`](../stacks-actions/SKILL.md). Source: [storage/framework/core/actions/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts).
|
|
117
117
|
|
|
118
|
-
Declared runtime exports: `BlogAdminError`, `DEFAULT_IOS_DEPENDENCIES`, `DEFAULT_STX_LINT_CONFIG`, `IosToolchainError`, `PUBLICATION_CHECK_SCRIPT`, `XCODE_NOTE`, `assertPublicationAllowed`, `blogSlugify`, `createComponent`, `createDatabase`, `createFactory`, `createFunction`, `createLanguage`, `createMail`, `createMiddleware`, `createMigration`, `createModel`, `createNotification`, `createPage`, `deleteBlogPost`, `describeDanglingRouteActions`, `describeGitHubRelease`, `discoverPackages`, `ensureDiscoveredPackages`, `findDanglingRouteActions`, `formatProject`, `getBlogPost`, `installStack`, `isDryRunActive`, `lintFix`, `lintProject`, `listBlogPosts`, `listStacks`, `loadIosDependencies`, `loadStxLintConfig`, `makeAction`, `makeCertificate`, `makeCommand`, `makeComponent`, `makeDatabase`, `makeFunction`, `makeJob`, `makeLanguage`, `makeMail`, `makeNotification`, `makePage`, `makePolicy`, `makeQueueTable`, `makeResource`, `makeStack`, `measureDefaultsDrift`, `pantryExecutable`, `pantryInstallArgs`, `parseFields`, `parseGitHubRemote`, `publicationChannels`, `publishGitHubRelease`, `resolveStxSource`, `resolveXcodegen`, `runAdd`, `runCommit`, `runMake`, `runStxLint`, `saveBlogPost`, `scaffoldCrud`, `setDryRun`, `summarizeStructureChanges`, `uninstallStack`, `validateReleaseEvidencePlan`, `verifyReleaseEvidence`, `xcodeDeveloperDir`.
|
|
118
|
+
Declared runtime exports: `BlogAdminError`, `DEFAULT_IOS_DEPENDENCIES`, `DEFAULT_STX_LINT_CONFIG`, `IosToolchainError`, `PUBLICATION_CHECK_SCRIPT`, `XCODE_NOTE`, `assertPublicationAllowed`, `blogSlugify`, `craftSupportsWebkit`, `createComponent`, `createDatabase`, `createFactory`, `createFunction`, `createLanguage`, `createMail`, `createMiddleware`, `createMigration`, `createModel`, `createNotification`, `createPage`, `deleteBlogPost`, `describeDanglingRouteActions`, `describeGitHubRelease`, `discoverPackages`, `ensureDiscoveredPackages`, `findDanglingRouteActions`, `formatProject`, `getBlogPost`, `installStack`, `isDryRunActive`, `lintFix`, `lintProject`, `listBlogPosts`, `listStacks`, `loadIosDependencies`, `loadStxLintConfig`, `macosAgentActionFiles`, `macosAgentDevFiles`, `macosAgentDevManifest`, `macosAgentEntry`, `macosAgentRouteFiles`, `makeAction`, `makeCertificate`, `makeCommand`, `makeComponent`, `makeDatabase`, `makeFunction`, `makeJob`, `makeLanguage`, `makeMail`, `makeNotification`, `makePage`, `makePolicy`, `makeQueueTable`, `makeResource`, `makeStack`, `measureDefaultsDrift`, `pantryExecutable`, `pantryInstallArgs`, `parseFields`, `parseGitHubRemote`, `prepareMacosAgent`, `prepareMacosNative`, `publicationChannels`, `publishGitHubRelease`, `resolveStxSource`, `resolveXcodegen`, `runAdd`, `runCommit`, `runMake`, `runStxLint`, `saveBlogPost`, `scaffoldCrud`, `setDryRun`, `summarizeStructureChanges`, `uninstallStack`, `validateReleaseEvidencePlan`, `verifyReleaseEvidence`, `xcodeDeveloperDir`.
|
|
119
119
|
|
|
120
|
-
Local source modules: [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/action.ts), [src/add.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/add.ts), [src/blog-admin.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/blog-admin.ts), [src/build/ios-toolchain.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/ios-toolchain.ts), [src/commit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/commit.ts), [src/dev/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/dev/index.ts), [src/discover-packages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/discover-packages.ts), [src/generate/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/generate/index.ts), [src/github-release.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/github-release.ts), [src/helpers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/helpers/index.ts), [src/library/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/library/index.ts), [src/lint/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/lint.ts), [src/lint/stx-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/stx-gate.ts), [src/make-command.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-command.ts), [src/make-job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-job.ts), [src/make-policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-policy.ts), [src/make-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-resource.ts), [src/make.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make.ts), [src/publication-preflight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/publication-preflight.ts), [src/release-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/release-evidence.ts), [src/scaffold-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/scaffold-crud.ts), [src/setup/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/setup/index.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stacks.ts), [src/stx-source.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stx-source.ts), [src/upgrade/package-project.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/package-project.ts), [src/upgrade/route-actions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/route-actions.ts).
|
|
120
|
+
Local source modules: [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/action.ts), [src/add.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/add.ts), [src/blog-admin.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/blog-admin.ts), [src/build/ios-toolchain.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/ios-toolchain.ts), [src/build/macos-native.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/macos-native.ts), [src/commit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/commit.ts), [src/dev/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/dev/index.ts), [src/discover-packages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/discover-packages.ts), [src/generate/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/generate/index.ts), [src/github-release.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/github-release.ts), [src/helpers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/helpers/index.ts), [src/library/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/library/index.ts), [src/lint/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/lint.ts), [src/lint/stx-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/stx-gate.ts), [src/make-command.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-command.ts), [src/make-job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-job.ts), [src/make-policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-policy.ts), [src/make-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-resource.ts), [src/make.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make.ts), [src/publication-preflight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/publication-preflight.ts), [src/release-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/release-evidence.ts), [src/scaffold-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/scaffold-crud.ts), [src/setup/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/setup/index.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stacks.ts), [src/stx-source.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stx-source.ts), [src/upgrade/package-project.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/package-project.ts), [src/upgrade/route-actions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/route-actions.ts).
|
|
121
121
|
|
|
122
|
-
Evidence directory: [
|
|
122
|
+
Evidence directory: [95 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
123
123
|
|
|
124
124
|
### @stacksjs/ai
|
|
125
125
|
|
|
@@ -127,9 +127,9 @@ Guidance: [`stacks-ai`](../stacks-ai/SKILL.md). Source: [storage/framework/core/
|
|
|
127
127
|
|
|
128
128
|
Declared runtime exports: `assistantTurn`, `buildMessageWithImages`, `clearUsageReporters`, `estimateMessageTokens`, `estimateTokens`, `fetchWithRetry`, `listUsageReporters`, `normalizeMessagesForProvider`, `onUsage`, `recordUsage`, `sanitizePrompt`, `toolResultsTurn`.
|
|
129
129
|
|
|
130
|
-
Local source modules: [src/agents/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/agents/index.ts), [src/buddy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/buddy.ts), [src/client.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/client.ts), [src/context.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/context.ts), [src/documents.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/documents.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/drivers/index.ts), [src/image.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/image.ts), [src/mcp-server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/mcp-server.ts), [src/mcp.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/mcp.ts), [src/models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/models.ts), [src/personalization.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/personalization.ts), [src/search.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/search.ts), [src/speech.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/speech.ts), [src/text.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/text.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/types.ts), [src/utils/client-bedrock-runtime.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/client-bedrock-runtime.ts), [src/utils/client-bedrock.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/client-bedrock.ts), [src/utils/model-access.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/model-access.ts), [src/utils/retry.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/retry.ts), [src/utils/tokens.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/tokens.ts), [src/utils/tools.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/tools.ts), [src/utils/usage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/usage.ts), [src/utils/vision.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/vision.ts).
|
|
130
|
+
Local source modules: [src/agents/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/agents/index.ts), [src/buddy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/buddy.ts), [src/client.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/client.ts), [src/complete.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/complete.ts), [src/context.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/context.ts), [src/documents.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/documents.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/drivers/index.ts), [src/image.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/image.ts), [src/mcp-server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/mcp-server.ts), [src/mcp.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/mcp.ts), [src/models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/models.ts), [src/personalization.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/personalization.ts), [src/search.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/search.ts), [src/speech.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/speech.ts), [src/text.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/text.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/types.ts), [src/utils/client-bedrock-runtime.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/client-bedrock-runtime.ts), [src/utils/client-bedrock.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/client-bedrock.ts), [src/utils/model-access.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/model-access.ts), [src/utils/retry.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/retry.ts), [src/utils/tokens.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/tokens.ts), [src/utils/tools.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/tools.ts), [src/utils/usage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/usage.ts), [src/utils/vision.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/utils/vision.ts).
|
|
131
131
|
|
|
132
|
-
Evidence directory: [
|
|
132
|
+
Evidence directory: [21 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
133
133
|
|
|
134
134
|
### @stacksjs/alias
|
|
135
135
|
|
|
@@ -217,7 +217,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
|
|
|
217
217
|
|
|
218
218
|
Local source modules: [src/commands/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/commands/index.ts).
|
|
219
219
|
|
|
220
|
-
Evidence directory: [
|
|
220
|
+
Evidence directory: [176 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
221
221
|
|
|
222
222
|
### @stacksjs/build
|
|
223
223
|
|
|
@@ -387,9 +387,9 @@ Guidance: [`stacks-desktop`](../stacks-desktop/SKILL.md). Source: [storage/frame
|
|
|
387
387
|
|
|
388
388
|
Declared runtime exports: `BUN_EXECUTABLE_MARKER`, `RESERVED_PLIST_KEYS`, `USERLAND_LAUNCHER`, `bundleDirectoryFor`, `codesignArgs`, `craftDevCommand`, `createUpdateManifestUrl`, `describeRuntimeDuplication`, `desktopAppVersion`, `desktopLauncherCompileArgs`, `dmgVolumeName`, `hasUserlandDesktopLauncher`, `isMachO`, `looksLikeBunExecutable`, `openDevWindow`, `plistValue`, `renderInfoPlist`, `renderUserlandPlistEntries`, `resolveCraftBinary`, `resolveCraftExecutable`, `resolveDesktopLauncher`, `resolveDevWindowUrl`, `resolveDmgPackaging`, `xmlEscape`.
|
|
389
389
|
|
|
390
|
-
Local source modules: [src/invites.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/invites.ts), [src/support.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/support.ts), [src/updater.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/updater.ts).
|
|
390
|
+
Local source modules: [src/agent-launcher.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/agent-launcher.ts), [src/agent.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/agent.ts), [src/invites.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/invites.ts), [src/macos-app.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/macos-app.ts), [src/macos-bundle.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/macos-bundle.ts), [src/support.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/support.ts), [src/updater.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/updater.ts).
|
|
391
391
|
|
|
392
|
-
Evidence directory: [
|
|
392
|
+
Evidence directory: [15 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
393
393
|
|
|
394
394
|
### @stacksjs/development
|
|
395
395
|
|
|
@@ -721,7 +721,7 @@ Evidence directory: [2 retained tests](https://github.com/stacksjs/stacks/blob/m
|
|
|
721
721
|
|
|
722
722
|
Guidance: [`stacks-router`](../stacks-router/SKILL.md). Source: [storage/framework/core/router/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/index.ts).
|
|
723
723
|
|
|
724
|
-
Declared runtime exports: `DASHBOARD_ROUTE_GROUPS`, `DEFAULT_ROUTE_BUNDLE_FEATURES`, `DEFAULT_ROUTE_REGISTRY`, `DatabaseSessionStore`, `EncryptedSessionStore`, `FileSessionStore`, `JSON_CONTENT_TYPE`, `MemorySessionStore`, `Middleware`, `PathParamError`, `RedisSessionStore`, `RequestBodyError`, `appRouteRegistry`, `assertRouteMiddlewareResolvable`, `bundleMounts`, `cacheRedisConnection`, `cacheRequestQuery`, `checkApplicationHealth`, `clearCsrfModuleCache`, `clearCurrentRequest`, `clearMiddlewareCache`, `clearRateLimit`, `clearRouteModelBindings`, `clearTrackedQueries`, `clientAddress`, `configureViewDirectories`, `createErrorResponse`, `createMiddlewareErrorResponse`, `createNotFoundResponse`, `createSessionStore`, `createStacksRouter`, `createStacksSessionStore`, `createTypedRouter`, `createValidationErrorResponse`, `dashboardGroupMiddleware`, `defineMiddleware`, `defineRouteModelBinding`, `describeUnknownDashboardGroups`, `disableViewRouting`, `enhanceRequest`, `fallbackStorage`, `findUnresolvableRouteMiddleware`, `getCurrentRequest`, `getQueryShapeCounts`, `getTraceId`, `installMiddlewareHotReload`, `isApiRequest`, `isRouterAction`, `listNamedRoutes`, `listRedirectRoutes`, `listRegisteredRoutes`, `listRootMountedAppRoutes`, `loadMiddlewareHandlers`, `loadRoutes`, `mountedDefaultRouteBundles`, `parseJsonText`, `rateLimit`, `rateLimitScale`, `rateLimitStatus`, `readJsonBody`, `readTextBody`, `request`, `resetBootHooks`, `resetRateLimiters`, `resetSharedRateLimitStorage`, `resetShutdownHooks`, `resolveDashboardAccess`, `resolveRouteModel`, `route`, `routeModelBindings`, `routeParams`, `runBootHooks`, `runHealthProbes`, `runShutdownHooks`, `runWithRequest`, `safePathParam`, `sanitizePathParam`, `scaledLimit`, `serve`, `serverResponse`, `setCurrentRequest`, `setRouteModelFallback`, `sharedRateLimitStorage`, `signUrl`, `signedUrl`, `stream`, `trackQuery`, `trustedProxies`, `url`, `useRateLimitStorage`, `verifySignedUrl`, `verifySignedUrlMiddleware`, `warnOnMultipleRouterInstances`, `withRouteAdmission`, `withTraceId`, `wrapAction`.
|
|
724
|
+
Declared runtime exports: `DASHBOARD_ROUTE_GROUPS`, `DEFAULT_ROUTE_BUNDLE_FEATURES`, `DEFAULT_ROUTE_REGISTRY`, `DatabaseSessionStore`, `EncryptedSessionStore`, `FileSessionStore`, `JSON_CONTENT_TYPE`, `MemorySessionStore`, `Middleware`, `PathParamError`, `RedisSessionStore`, `RequestBodyError`, `appRouteRegistry`, `assertRouteMiddlewareResolvable`, `bundleMounts`, `cacheRedisConnection`, `cacheRequestQuery`, `checkApplicationHealth`, `clearCsrfModuleCache`, `clearCurrentRequest`, `clearMiddlewareCache`, `clearRateLimit`, `clearRouteModelBindings`, `clearTrackedQueries`, `clientAddress`, `configureViewDirectories`, `createErrorResponse`, `createMiddlewareErrorResponse`, `createNotFoundResponse`, `createSessionStore`, `createStacksRouter`, `createStacksSessionStore`, `createTypedRouter`, `createValidationErrorResponse`, `dashboardGroupMiddleware`, `defineMiddleware`, `defineRouteModelBinding`, `describeUnknownDashboardGroups`, `disableViewRouting`, `enhanceRequest`, `fallbackStorage`, `findUnresolvableRouteMiddleware`, `getCurrentRequest`, `getQueryShapeCounts`, `getTraceId`, `installMiddlewareHotReload`, `isApiRequest`, `isRouterAction`, `listNamedRoutes`, `listRedirectRoutes`, `listRegisteredRoutes`, `listRootMountedAppRoutes`, `loadMiddlewareHandlers`, `loadRoutes`, `mountedDefaultRouteBundles`, `parseJsonText`, `provideActions`, `rateLimit`, `rateLimitScale`, `rateLimitStatus`, `readJsonBody`, `readTextBody`, `request`, `resetBootHooks`, `resetRateLimiters`, `resetSharedRateLimitStorage`, `resetShutdownHooks`, `resolveDashboardAccess`, `resolveRouteModel`, `route`, `routeModelBindings`, `routeParams`, `runBootHooks`, `runHealthProbes`, `runShutdownHooks`, `runWithRequest`, `safePathParam`, `sanitizePathParam`, `scaledLimit`, `serve`, `serverResponse`, `setCurrentRequest`, `setRouteModelFallback`, `sharedRateLimitStorage`, `signUrl`, `signedUrl`, `stream`, `trackQuery`, `trustedProxies`, `url`, `useRateLimitStorage`, `verifySignedUrl`, `verifySignedUrlMiddleware`, `warnOnMultipleRouterInstances`, `withRouteAdmission`, `withTraceId`, `wrapAction`.
|
|
725
725
|
|
|
726
726
|
Local source modules: [src/api-shape.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/api-shape.ts), [src/body.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/body.ts), [src/dashboard-access.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/dashboard-access.ts), [src/encrypted-session-store.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/encrypted-session-store.ts), [src/error-handler.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/error-handler.ts), [src/health.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/health.ts), [src/json.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/json.ts), [src/middleware.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/middleware.ts), [src/path-sanitize.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/path-sanitize.ts), [src/rate-limit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/rate-limit.ts), [src/request-augmentation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/request-augmentation.ts), [src/request-context.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/request-context.ts), [src/route-loader.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/route-loader.ts), [src/route-model-binding.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/route-model-binding.ts), [src/security-settings.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/security-settings.ts), [src/session-factory.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/session-factory.ts), [src/signed-url.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/signed-url.ts), [src/stacks-router.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/stacks-router.ts), [src/typed-router.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/typed-router.ts).
|
|
727
727
|
|
|
@@ -755,7 +755,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
|
|
|
755
755
|
|
|
756
756
|
Local source modules: [src/api-key.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/api-key.ts), [src/crypt.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/crypt.ts), [src/hash.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/hash.ts), [src/key.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/key.ts), [src/outbound.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/outbound.ts), [src/regex.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/regex.ts), [src/webhook.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/webhook.ts).
|
|
757
757
|
|
|
758
|
-
Evidence directory: [
|
|
758
|
+
Evidence directory: [12 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
759
759
|
|
|
760
760
|
### @stacksjs/server
|
|
761
761
|
|
|
@@ -879,7 +879,7 @@ Guidance: [`stacks-types`](../stacks-types/SKILL.md). Source: [storage/framework
|
|
|
879
879
|
|
|
880
880
|
Read the entrypoint and package export map for re-exported or type-only surfaces.
|
|
881
881
|
|
|
882
|
-
Local source modules: [src/ai.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ai.ts), [src/analytics.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/analytics.ts), [src/api.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/api.ts), [src/app.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/app.ts), [src/auction.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auction.ts), [src/auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auth.ts), [src/auto-imports.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auto-imports.ts), [src/binary.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/binary.ts), [src/cache.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cache.ts), [src/cdn.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cdn.ts), [src/chat.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/chat.ts), [src/cli.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cli.ts), [src/cloud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cloud.ts), [src/cms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cms.ts), [src/commands.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/commands.ts), [src/commerce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/commerce.ts), [src/components.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/components.ts), [src/configure.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/configure.ts), [src/cors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cors.ts), [src/cron-jobs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cron-jobs.ts), [src/dashboard.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dashboard.ts), [src/database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/database.ts), [src/dependencies.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dependencies.ts), [src/deploy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/deploy.ts), [src/dns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dns.ts), [src/docs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/docs.ts), [src/email.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/email.ts), [src/env.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/env.ts), [src/errors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/errors.ts), [src/events.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/events.ts), [src/exit-code.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/exit-code.ts), [src/feature-flags.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/feature-flags.ts), [src/file-systems.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/file-systems.ts), [src/forms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/forms.ts), [src/git.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/git.ts), [src/hashing.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/hashing.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/helpers.ts), [src/i18n.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/i18n.ts), [src/images.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/images.ts), [src/library.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/library.ts), [src/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/lint.ts), [src/logging.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/logging.ts), [src/manifest.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/manifest.ts), [src/marketing.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/marketing.ts), [src/mobile.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/mobile.ts), [src/model-dashboard-augmentation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model-dashboard-augmentation.ts), [src/model-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model-names.ts), [src/model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model.ts), [src/monitoring.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/monitoring.ts), [src/notifications.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/notifications.ts), [src/oauth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/oauth.ts), [src/pages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/pages.ts), [src/payments.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/payments.ts), [src/phone.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/phone.ts), [src/ports.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ports.ts), [src/promise.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/promise.ts), [src/push.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/push.ts), [src/queue.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/queue.ts), [src/reactivity.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/reactivity.ts), [src/realtime.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/realtime.ts), [src/request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/request.ts), [src/response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/response.ts), [src/router.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/router.ts), [src/saas.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/saas.ts), [src/scheduler.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/scheduler.ts), [src/search-engine.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/search-engine.ts), [src/security.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/security.ts), [src/seo.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/seo.ts), [src/server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/server.ts), [src/services.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/services.ts), [src/settings-config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/settings-config.ts), [src/sites.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/sites.ts), [src/sms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/sms.ts), [src/socials.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/socials.ts), [src/stack-extensions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/stack-extensions.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/stacks.ts), [src/storage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/storage.ts), [src/table-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/table-names.ts), [src/tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/tables.ts), [src/team.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/team.ts), [src/ui.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ui.ts), [src/utils.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/utils.ts).
|
|
882
|
+
Local source modules: [src/ai.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ai.ts), [src/analytics.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/analytics.ts), [src/api.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/api.ts), [src/app.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/app.ts), [src/auction.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auction.ts), [src/auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auth.ts), [src/auto-imports.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/auto-imports.ts), [src/binary.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/binary.ts), [src/cache.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cache.ts), [src/cdn.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cdn.ts), [src/chat.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/chat.ts), [src/cli.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cli.ts), [src/cloud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cloud.ts), [src/cms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cms.ts), [src/commands.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/commands.ts), [src/commerce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/commerce.ts), [src/components.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/components.ts), [src/configure.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/configure.ts), [src/cors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cors.ts), [src/cron-jobs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/cron-jobs.ts), [src/dashboard.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dashboard.ts), [src/database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/database.ts), [src/dependencies.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dependencies.ts), [src/deploy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/deploy.ts), [src/desktop.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/desktop.ts), [src/dns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/dns.ts), [src/docs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/docs.ts), [src/email.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/email.ts), [src/env.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/env.ts), [src/errors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/errors.ts), [src/events.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/events.ts), [src/exit-code.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/exit-code.ts), [src/feature-flags.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/feature-flags.ts), [src/file-systems.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/file-systems.ts), [src/forms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/forms.ts), [src/git.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/git.ts), [src/hashing.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/hashing.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/helpers.ts), [src/i18n.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/i18n.ts), [src/images.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/images.ts), [src/library.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/library.ts), [src/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/lint.ts), [src/logging.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/logging.ts), [src/manifest.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/manifest.ts), [src/marketing.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/marketing.ts), [src/mobile.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/mobile.ts), [src/model-dashboard-augmentation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model-dashboard-augmentation.ts), [src/model-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model-names.ts), [src/model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/model.ts), [src/monitoring.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/monitoring.ts), [src/notifications.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/notifications.ts), [src/oauth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/oauth.ts), [src/pages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/pages.ts), [src/payments.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/payments.ts), [src/phone.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/phone.ts), [src/ports.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ports.ts), [src/promise.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/promise.ts), [src/push.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/push.ts), [src/queue.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/queue.ts), [src/reactivity.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/reactivity.ts), [src/realtime.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/realtime.ts), [src/request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/request.ts), [src/response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/response.ts), [src/router.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/router.ts), [src/saas.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/saas.ts), [src/scheduler.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/scheduler.ts), [src/search-engine.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/search-engine.ts), [src/security.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/security.ts), [src/seo.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/seo.ts), [src/server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/server.ts), [src/services.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/services.ts), [src/settings-config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/settings-config.ts), [src/sites.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/sites.ts), [src/sms.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/sms.ts), [src/socials.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/socials.ts), [src/stack-extensions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/stack-extensions.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/stacks.ts), [src/storage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/storage.ts), [src/table-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/table-names.ts), [src/tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/tables.ts), [src/team.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/team.ts), [src/ui.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/ui.ts), [src/utils.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/utils.ts).
|
|
883
883
|
|
|
884
884
|
Evidence directory: [2 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
885
885
|
|
|
@@ -22,6 +22,32 @@ security/src/
|
|
|
22
22
|
└── hash.ts # password hashing (bcrypt/argon2)
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Scanning a project: `buddy security:scan`
|
|
26
|
+
|
|
27
|
+
`buddy security:scan` (alias `buddy audit`) checks a project for security problems and exits non-zero on findings at or above `--fail-on` (default `high`), so it drops into CI. Five checks, each runnable alone with `--only` or left out with `--skip`:
|
|
28
|
+
|
|
29
|
+
| Check | Finds |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `dependencies` | Known vulnerabilities in the lockfile (`bun audit`; needs the network, skipped with `--offline`) |
|
|
32
|
+
| `secrets` | Committed credentials: private keys, AWS/Stripe/GitHub/Anthropic/OpenAI/Slack/Google/Twilio/SendGrid/npm tokens, database URLs with passwords, `secret = "high-entropy value"` |
|
|
33
|
+
| `code` | `eval` / `new Function`, shell commands built from strings, SQL built with interpolation, disabled TLS verification, `alg: none`, `innerHTML`, `Math.random()` for tokens, MD5/SHA-1, CORS `*` with credentials |
|
|
34
|
+
| `workflows` | GitHub Actions that paste untrusted text into `run:`, check out a pull request under `pull_request_target`, echo secrets, or follow a branch |
|
|
35
|
+
| `hygiene` | Committed `.env` files with readable secrets (encrypted values are fine), key files, a `.gitignore` without `.env`, no lockfile |
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
buddy security:scan # everything, fail on high or worse
|
|
39
|
+
buddy security:scan --only dependencies,secrets --fail-on medium
|
|
40
|
+
buddy security:scan --json # the report, for tooling
|
|
41
|
+
buddy security:scan --show-ignored # what exceptions set aside
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A finding that is fine is set aside with a reason, never silently:
|
|
45
|
+
|
|
46
|
+
- On the line (or the line above): `// security-ignore: code/inner-html the HTML is sanitized by sanitize()`
|
|
47
|
+
- In `.security-ignore.json`: `{ "ignore": [{ "rule": "code/sql-interpolation", "path": "database/seed.ts", "reason": "ids from rows it just selected", "expires": "2027-06-30" }] }`. `rule` takes `code/*`; `path` is a file or a directory ending in `/`; for an advisory use `"reference": "GHSA-…"` or the package name. An entry without a reason, or past its `expires`, is reported and no longer applies.
|
|
48
|
+
|
|
49
|
+
A check that cannot run (offline, no `bun.lock`) is listed under "not checked", never reported as clean. Programmatic use: `import { runSecurityScan } from '@stacksjs/security/scan'`.
|
|
50
|
+
|
|
25
51
|
## App Key Generation
|
|
26
52
|
|
|
27
53
|
```typescript
|
|
@@ -10,6 +10,10 @@ allowed-tools: Read Edit Write Bash Grep Glob
|
|
|
10
10
|
|
|
11
11
|
You are performing a security analysis for a Stacks application. Be concrete — every finding must include a realistic exploit scenario. Vague warnings are worthless.
|
|
12
12
|
|
|
13
|
+
## Step 0: Run the scanner
|
|
14
|
+
|
|
15
|
+
Run `buddy security:scan --show-ignored` first (see the `stacks-security` skill). It already covers vulnerable dependencies, committed secrets, dangerous calls, risky GitHub workflows and repository hygiene, so do not repeat those by hand: verify each finding it reports (read the code, confirm it is reachable) and spend your own effort on what a pattern scan cannot see: authorization gaps, business-logic abuse, trust boundaries and data exposure. Treat every `security-ignore` reason as a claim to check.
|
|
16
|
+
|
|
13
17
|
## Determine Scope
|
|
14
18
|
|
|
15
19
|
1. If the user specifies files or a feature, analyze that scope
|
|
@@ -185,7 +185,8 @@ through STX's asynchronous render boundary. Pair tenant features with
|
|
|
185
185
|
`stacks-sites`.
|
|
186
186
|
|
|
187
187
|
The browser has both eagerly delivered and demand-bundled composables.
|
|
188
|
-
Observers, motion helpers
|
|
188
|
+
Observers, motion helpers, STX `useForm` and `useCompletion` (inline AI ghost
|
|
189
|
+
text; `<AiTextarea>` is the ready-made textarea) are usable client primitives in
|
|
189
190
|
current STX, even when they are not explicit `window.name` aliases. Read
|
|
190
191
|
`stacks-composables/BROWSER.md` before choosing a signature or mixing the
|
|
191
192
|
browser signal API with explicit module Refs.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ConfiguredAIOptions } from '@stacksjs/ai'
|
|
2
|
+
import type { RequestInstance } from '@stacksjs/types'
|
|
3
|
+
import { Action } from '@stacksjs/actions/runtime'
|
|
4
|
+
import { complete, completionStatus } from '@stacksjs/ai'
|
|
5
|
+
import { resolveAuthenticatedUser } from '@stacksjs/auth'
|
|
6
|
+
import { config } from '@stacksjs/config'
|
|
7
|
+
import { log } from '@stacksjs/logging'
|
|
8
|
+
import type { ResponseStatus } from '@stacksjs/router'
|
|
9
|
+
import { rateLimit, response } from '@stacksjs/router'
|
|
10
|
+
import { COMPLETE_RATE_PER_MINUTE, handleCompleteRequest } from './complete-request'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* `POST /ai/complete`: the ghost text behind an editor's Tab-to-accept.
|
|
14
|
+
*
|
|
15
|
+
* Body `{ before, after?, kind?: 'note' | 'prompt' | 'todo' | 'text', context? }`,
|
|
16
|
+
* answer `{ completion }`. `''` means "no suggestion", including when the app
|
|
17
|
+
* has no AI driver configured; a provider failure is a 502.
|
|
18
|
+
*
|
|
19
|
+
* Needs a signed-in user and is rate limited per user. Mount it under another
|
|
20
|
+
* path with `route.post('/complete', 'Actions/AI/CompleteAction').middleware('auth')`.
|
|
21
|
+
*/
|
|
22
|
+
export default new Action({
|
|
23
|
+
name: 'AiCompleteAction',
|
|
24
|
+
description: 'Complete the text at the cursor with the configured AI driver',
|
|
25
|
+
method: 'POST',
|
|
26
|
+
apiResponse: true,
|
|
27
|
+
|
|
28
|
+
async handle(request: RequestInstance) {
|
|
29
|
+
const aiConfig = (config.ai || {}) as ConfiguredAIOptions
|
|
30
|
+
const body = {
|
|
31
|
+
before: request.get('before'),
|
|
32
|
+
after: request.get('after'),
|
|
33
|
+
kind: request.get('kind'),
|
|
34
|
+
context: request.get('context'),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const result = await handleCompleteRequest({
|
|
38
|
+
body,
|
|
39
|
+
config: aiConfig,
|
|
40
|
+
authenticate: () => resolveAuthenticatedUser(request as any),
|
|
41
|
+
limit: userId => rateLimit('ai-complete', COMPLETE_RATE_PER_MINUTE, { identity: `user:${userId}` }).per('minute'),
|
|
42
|
+
available: cfg => completionStatus(cfg).available,
|
|
43
|
+
complete: input => complete(input, { config: aiConfig }),
|
|
44
|
+
signal: (request as { signal?: AbortSignal }).signal,
|
|
45
|
+
log: (message, context) => void log.error(message, context),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return response.json(result.body, result.status as ResponseStatus)
|
|
49
|
+
},
|
|
50
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import { readFileSync } from 'node:fs'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
describe('CompleteAction wiring', () => {
|
|
6
|
+
test('is a POST action the default /ai route group mounts', () => {
|
|
7
|
+
const routes = readFileSync(join(import.meta.dir, '../../../routes/dashboard.ts'), 'utf8')
|
|
8
|
+
expect(routes).toContain('route.post(\'/complete\', \'Actions/AI/CompleteAction\')')
|
|
9
|
+
// Inside the guarded `/ai` group, so it is mounted at /ai/complete behind auth.
|
|
10
|
+
const group = routes.slice(routes.indexOf('route.group({ prefix: \'/ai\''))
|
|
11
|
+
expect(group.indexOf('/complete')).toBeGreaterThan(0)
|
|
12
|
+
expect(group.indexOf('/complete')).toBeLessThan(group.indexOf('})'))
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('loads and declares POST', async () => {
|
|
16
|
+
const action = (await import('./CompleteAction')).default as { name?: string, method?: string }
|
|
17
|
+
expect(action.method).toBe('POST')
|
|
18
|
+
expect(action.name).toBe('AiCompleteAction')
|
|
19
|
+
})
|
|
20
|
+
})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { CompleteRequestDeps } from './complete-request'
|
|
2
|
+
import { describe, expect, test } from 'bun:test'
|
|
3
|
+
import { COMPLETE_MAX_BEFORE, handleCompleteRequest, parseCompleteBody } from './complete-request'
|
|
4
|
+
|
|
5
|
+
function deps(overrides: Partial<CompleteRequestDeps> = {}): CompleteRequestDeps & { calls: unknown[], limited: Array<number | string> } {
|
|
6
|
+
const calls: unknown[] = []
|
|
7
|
+
const limited: Array<number | string> = []
|
|
8
|
+
return {
|
|
9
|
+
calls,
|
|
10
|
+
limited,
|
|
11
|
+
body: { before: 'Remember to buy ', kind: 'todo' },
|
|
12
|
+
config: { default: 'anthropic' },
|
|
13
|
+
authenticate: async () => ({ id: 7 }),
|
|
14
|
+
limit: async (id) => { limited.push(id) },
|
|
15
|
+
available: () => true,
|
|
16
|
+
complete: async (input) => {
|
|
17
|
+
calls.push(input)
|
|
18
|
+
return { completion: 'milk' }
|
|
19
|
+
},
|
|
20
|
+
...overrides,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('POST /ai/complete', () => {
|
|
25
|
+
test('requires a signed-in user', async () => {
|
|
26
|
+
const d = deps({ authenticate: async () => undefined })
|
|
27
|
+
const result = await handleCompleteRequest(d)
|
|
28
|
+
expect(result.status).toBe(401)
|
|
29
|
+
expect(d.calls).toHaveLength(0)
|
|
30
|
+
expect(d.limited).toHaveLength(0)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('an auth backend failure is a 503, not a silent pass', async () => {
|
|
34
|
+
const result = await handleCompleteRequest(deps({ authenticate: async () => { throw new Error('db down') } }))
|
|
35
|
+
expect(result.status).toBe(503)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('validates the body', async () => {
|
|
39
|
+
expect((await handleCompleteRequest(deps({ body: {} }))).status).toBe(422)
|
|
40
|
+
expect((await handleCompleteRequest(deps({ body: { before: 5 } }))).status).toBe(422)
|
|
41
|
+
expect((await handleCompleteRequest(deps({ body: { before: 'x', kind: 'poem' } }))).status).toBe(422)
|
|
42
|
+
expect((await handleCompleteRequest(deps({ body: { before: 'x', after: 5 } }))).status).toBe(422)
|
|
43
|
+
expect((await handleCompleteRequest(deps({ body: { before: 'x'.repeat(COMPLETE_MAX_BEFORE + 1) } }))).status).toBe(422)
|
|
44
|
+
expect(parseCompleteBody({ before: 'x' })).toEqual({ ok: true, value: { before: 'x', after: '', kind: 'text', context: '' } })
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('returns the completion and spends one slot of that user\'s budget', async () => {
|
|
48
|
+
const d = deps({ body: { before: 'Remember to buy ', after: '', kind: 'todo', context: 'Groceries' } })
|
|
49
|
+
const result = await handleCompleteRequest(d)
|
|
50
|
+
expect(result).toEqual({ status: 200, body: { completion: 'milk' } })
|
|
51
|
+
expect(d.limited).toEqual([7])
|
|
52
|
+
expect(d.calls[0]).toMatchObject({ before: 'Remember to buy ', kind: 'todo', context: 'Groceries' })
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('answers an empty completion, not an error, when no AI driver is configured', async () => {
|
|
56
|
+
const d = deps({ available: () => false })
|
|
57
|
+
const result = await handleCompleteRequest(d)
|
|
58
|
+
expect(result).toEqual({ status: 200, body: { completion: '' } })
|
|
59
|
+
expect(d.calls).toHaveLength(0)
|
|
60
|
+
expect(d.limited).toHaveLength(0)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('nothing to continue is an empty completion without a model call', async () => {
|
|
64
|
+
const d = deps({ body: { before: ' \n' } })
|
|
65
|
+
expect(await handleCompleteRequest(d)).toEqual({ status: 200, body: { completion: '' } })
|
|
66
|
+
expect(d.calls).toHaveLength(0)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('a provider failure is a 502 with a clear message', async () => {
|
|
70
|
+
const logged: string[] = []
|
|
71
|
+
const result = await handleCompleteRequest(deps({
|
|
72
|
+
complete: async () => { throw new Error('Claude API error: overloaded') },
|
|
73
|
+
log: message => void logged.push(message),
|
|
74
|
+
}))
|
|
75
|
+
expect(result.status).toBe(502)
|
|
76
|
+
expect(result.body).toEqual({ message: 'The AI provider could not complete the text.' })
|
|
77
|
+
expect(logged).toHaveLength(1)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('an aborted request is not reported as a failure', async () => {
|
|
81
|
+
const abort = Object.assign(new Error('aborted'), { name: 'AbortError' })
|
|
82
|
+
const result = await handleCompleteRequest(deps({ complete: async () => { throw abort } }))
|
|
83
|
+
expect(result).toEqual({ status: 200, body: { completion: '' } })
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('the rate limit rejection propagates for the framework to turn into a 429', async () => {
|
|
87
|
+
const d = deps({ limit: async () => { throw Object.assign(new Error('Too many requests'), { status: 429 }) } })
|
|
88
|
+
await expect(handleCompleteRequest(d)).rejects.toMatchObject({ status: 429 })
|
|
89
|
+
expect(d.calls).toHaveLength(0)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { CompleteInput, CompletionKind, ConfiguredAIOptions } from '@stacksjs/ai'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The testable core of `POST /ai/complete`. The Action reads the request and
|
|
5
|
+
* hands this its parts; everything decided here is a status and a body.
|
|
6
|
+
*
|
|
7
|
+
* Two answers matter to an editor drawing ghost text:
|
|
8
|
+
* - `200 { completion: '' }` is "no suggestion", and it covers a missing or
|
|
9
|
+
* disabled AI driver, so an app without AI keys never shows an error while
|
|
10
|
+
* someone types.
|
|
11
|
+
* - `502` is a real provider failure, with a message worth logging.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export const COMPLETE_MAX_BEFORE = 20_000
|
|
15
|
+
export const COMPLETE_MAX_AFTER = 5_000
|
|
16
|
+
export const COMPLETE_MAX_CONTEXT = 2_000
|
|
17
|
+
/** Suggestions per user per minute. The client debounces; this is the backstop. */
|
|
18
|
+
export const COMPLETE_RATE_PER_MINUTE = 90
|
|
19
|
+
|
|
20
|
+
const KINDS: readonly CompletionKind[] = ['note', 'prompt', 'todo', 'text']
|
|
21
|
+
|
|
22
|
+
export interface CompleteRequestBody {
|
|
23
|
+
before?: unknown
|
|
24
|
+
after?: unknown
|
|
25
|
+
kind?: unknown
|
|
26
|
+
context?: unknown
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ParsedCompleteBody {
|
|
30
|
+
before: string
|
|
31
|
+
after: string
|
|
32
|
+
kind: CompletionKind
|
|
33
|
+
context: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function parseCompleteBody(body: CompleteRequestBody): { ok: true, value: ParsedCompleteBody } | { ok: false, message: string } {
|
|
37
|
+
if (typeof body.before !== 'string')
|
|
38
|
+
return { ok: false, message: 'The before field must be the text before the cursor.' }
|
|
39
|
+
if (body.before.length > COMPLETE_MAX_BEFORE)
|
|
40
|
+
return { ok: false, message: `The before field must be ${COMPLETE_MAX_BEFORE} characters or fewer.` }
|
|
41
|
+
|
|
42
|
+
if (body.after !== undefined && body.after !== null && typeof body.after !== 'string')
|
|
43
|
+
return { ok: false, message: 'The after field must be the text after the cursor.' }
|
|
44
|
+
if (typeof body.after === 'string' && body.after.length > COMPLETE_MAX_AFTER)
|
|
45
|
+
return { ok: false, message: `The after field must be ${COMPLETE_MAX_AFTER} characters or fewer.` }
|
|
46
|
+
|
|
47
|
+
if (body.kind !== undefined && body.kind !== null && !KINDS.includes(body.kind as CompletionKind))
|
|
48
|
+
return { ok: false, message: `The kind field must be one of ${KINDS.join(', ')}.` }
|
|
49
|
+
|
|
50
|
+
if (body.context !== undefined && body.context !== null && typeof body.context !== 'string')
|
|
51
|
+
return { ok: false, message: 'The context field must be text.' }
|
|
52
|
+
if (typeof body.context === 'string' && body.context.length > COMPLETE_MAX_CONTEXT)
|
|
53
|
+
return { ok: false, message: `The context field must be ${COMPLETE_MAX_CONTEXT} characters or fewer.` }
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
ok: true,
|
|
57
|
+
value: {
|
|
58
|
+
before: body.before,
|
|
59
|
+
after: typeof body.after === 'string' ? body.after : '',
|
|
60
|
+
kind: (body.kind as CompletionKind | undefined | null) ?? 'text',
|
|
61
|
+
context: typeof body.context === 'string' ? body.context : '',
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface CompleteRequestDeps {
|
|
67
|
+
body: CompleteRequestBody
|
|
68
|
+
/** Resolves the signed-in user, or undefined. Throws when auth itself broke. */
|
|
69
|
+
authenticate: () => Promise<{ id: number | string } | undefined>
|
|
70
|
+
/** Consumes one slot of the user's budget; throws an HttpError(429) when spent. */
|
|
71
|
+
limit: (userId: number | string) => Promise<void>
|
|
72
|
+
config: ConfiguredAIOptions
|
|
73
|
+
complete: (input: CompleteInput) => Promise<{ completion: string }>
|
|
74
|
+
/** Whether a driver can answer at all; false answers `''` without a call. */
|
|
75
|
+
available: (config: ConfiguredAIOptions) => boolean
|
|
76
|
+
signal?: AbortSignal
|
|
77
|
+
log?: (message: string, context: Record<string, unknown>) => void
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface CompleteRequestResult {
|
|
81
|
+
status: number
|
|
82
|
+
body: { completion: string } | { message: string }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function handleCompleteRequest(deps: CompleteRequestDeps): Promise<CompleteRequestResult> {
|
|
86
|
+
let user
|
|
87
|
+
try {
|
|
88
|
+
user = await deps.authenticate()
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
deps.log?.('[ai] Completion auth failed', { error })
|
|
92
|
+
return { status: 503, body: { message: 'Authentication could not be verified.' } }
|
|
93
|
+
}
|
|
94
|
+
if (!user?.id)
|
|
95
|
+
return { status: 401, body: { message: 'Sign in to use completions.' } }
|
|
96
|
+
|
|
97
|
+
const parsed = parseCompleteBody(deps.body)
|
|
98
|
+
if (!parsed.ok)
|
|
99
|
+
return { status: 422, body: { message: parsed.message } }
|
|
100
|
+
|
|
101
|
+
// Nothing to continue, or nowhere to ask: the same quiet answer, and no
|
|
102
|
+
// budget spent.
|
|
103
|
+
if (!parsed.value.before.trim() || !deps.available(deps.config))
|
|
104
|
+
return { status: 200, body: { completion: '' } }
|
|
105
|
+
|
|
106
|
+
await deps.limit(user.id)
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const { completion } = await deps.complete({ ...parsed.value, signal: deps.signal })
|
|
110
|
+
return { status: 200, body: { completion } }
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// The client moved on (aborted its request): not a failure to report.
|
|
114
|
+
if ((error as Error)?.name === 'AbortError')
|
|
115
|
+
return { status: 200, body: { completion: '' } }
|
|
116
|
+
deps.log?.('[ai] Completion request failed', { error })
|
|
117
|
+
return { status: 502, body: { message: 'The AI provider could not complete the text.' } }
|
|
118
|
+
}
|
|
119
|
+
}
|
package/ide/vscode/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"publisher": "Stacks",
|
|
3
3
|
"name": "vscode-stacks",
|
|
4
4
|
"displayName": "Stacks",
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.398",
|
|
6
6
|
"description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.398",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/stacksjs/stacks.git",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@iconify-json/f7": "^1.2.2",
|
|
47
47
|
"@iconify-json/hugeicons": "^1.2.35",
|
|
48
|
-
"@stacksjs/mobile": "0.75.
|
|
49
|
-
"@stacksjs/sanitizer": "0.2.
|
|
50
|
-
"@stacksjs/stx": "0.2.
|
|
48
|
+
"@stacksjs/mobile": "0.75.398",
|
|
49
|
+
"@stacksjs/sanitizer": "0.2.775",
|
|
50
|
+
"@stacksjs/stx": "0.2.775",
|
|
51
51
|
"@xterm/addon-fit": "^0.11.0",
|
|
52
52
|
"@xterm/xterm": "^6.0.0",
|
|
53
53
|
"ts-qr-codes": "^0.1.8"
|
|
@@ -12,14 +12,21 @@
|
|
|
12
12
|
*/
|
|
13
13
|
const title = useReactiveProp('title', '')
|
|
14
14
|
const subtitle = useReactiveProp('subtitle', '')
|
|
15
|
+
// The mark above the heading. An app brands it with an Iconify class, a short line above the title, or its own
|
|
16
|
+
// markup in the `brand` slot, without forking the four pages that sit in this card (stacksjs/stacks#3086).
|
|
17
|
+
const icon = useReactiveProp('icon', 'i-hugeicons-cube')
|
|
18
|
+
const eyebrow = useReactiveProp('eyebrow', '')
|
|
15
19
|
</script>
|
|
16
20
|
|
|
17
21
|
<div class="flex items-center justify-center px-4 py-12 min-h-screen">
|
|
18
22
|
<div class="max-w-sm w-full">
|
|
19
23
|
<div class="mb-8 text-center">
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
|
|
24
|
+
<slot name="brand">
|
|
25
|
+
<div class="inline-flex items-center justify-center mb-4 h-12 w-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl shadow-blue-500/25 shadow-lg">
|
|
26
|
+
<span class="h-7 w-7 text-white" :class="icon()"></span>
|
|
27
|
+
</div>
|
|
28
|
+
</slot>
|
|
29
|
+
<p :if="eyebrow()" class="mb-1 font-semibold text-blue-600 text-xs tracking-widest uppercase dark:text-blue-400">{{ eyebrow() }}</p>
|
|
23
30
|
<h1 class="font-semibold text-2xl text-neutral-900 dark:text-white">{{ title() }}</h1>
|
|
24
31
|
<p class="mt-2 text-neutral-500 text-sm dark:text-neutral-400">{{ subtitle() }}</p>
|
|
25
32
|
</div>
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
const emit = defineEmits(['submit', 'retry'])
|
|
5
5
|
const title = useReactiveProp<string>('title', 'Forgot password?')
|
|
6
6
|
const subtitle = useReactiveProp<string>('subtitle', 'Enter your email and we\'ll send you a reset link')
|
|
7
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
8
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
7
9
|
const isLoading = useReactiveProp<boolean>('isLoading', false)
|
|
8
10
|
const error = useReactiveProp<string>('error', '')
|
|
9
11
|
const success = useReactiveProp<boolean>('success', false)
|
|
@@ -19,7 +21,7 @@ function retry(): void {
|
|
|
19
21
|
emit('retry')
|
|
20
22
|
}
|
|
21
23
|
</script>
|
|
22
|
-
<AuthCard :title="title()" :subtitle="subtitle()">
|
|
24
|
+
<AuthCard :title="title()" :subtitle="subtitle()" :icon="icon()" :eyebrow="eyebrow()">
|
|
23
25
|
|
|
24
26
|
<!-- Form Card -->
|
|
25
27
|
<div class="p-6 bg-white dark:bg-neutral-900 border border-neutral-200/60 rounded-2xl dark:border-neutral-800 shadow-black/5 shadow-xl dark:shadow-black/20">
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
// "dashboardApi is not defined", which the catch below then showed to the
|
|
7
7
|
// visitor as the reason their reset link could not be sent.
|
|
8
8
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
9
|
+
// Branding passes through to the card: an Iconify class for the mark and a short line above the title (stacksjs/stacks#3086).
|
|
10
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
11
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
9
12
|
|
|
10
13
|
const isLoading = state(false)
|
|
11
14
|
const error = state('')
|
|
@@ -39,6 +42,8 @@ function handleRetry(): void {
|
|
|
39
42
|
|
|
40
43
|
<template>
|
|
41
44
|
<ForgotPassword
|
|
45
|
+
:icon="icon()"
|
|
46
|
+
:eyebrow="eyebrow()"
|
|
42
47
|
@submit="handleForgotPassword"
|
|
43
48
|
@retry="handleRetry"
|
|
44
49
|
:isLoading="isLoading()"
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
const emit = defineEmits(['submit'])
|
|
5
5
|
const title = useReactiveProp<string>('title', 'Welcome back')
|
|
6
6
|
const subtitle = useReactiveProp<string>('subtitle', 'Sign in to your account')
|
|
7
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
8
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
7
9
|
const isLoading = useReactiveProp<boolean>('isLoading', false)
|
|
8
10
|
const error = useReactiveProp<string>('error', '')
|
|
9
11
|
const showRememberMe = useReactiveProp<boolean>('showRememberMe', true)
|
|
@@ -56,7 +58,7 @@ function handleSubmit(): void {
|
|
|
56
58
|
}
|
|
57
59
|
</script>
|
|
58
60
|
|
|
59
|
-
<AuthCard :title="title()" :subtitle="subtitle()">
|
|
61
|
+
<AuthCard :title="title()" :subtitle="subtitle()" :icon="icon()" :eyebrow="eyebrow()">
|
|
60
62
|
|
|
61
63
|
<div class="p-6 bg-white dark:bg-neutral-900 border border-neutral-200/60 rounded-2xl dark:border-neutral-800 shadow-black/5 shadow-xl dark:shadow-black/20">
|
|
62
64
|
<div :if="error()" role="alert" class="mb-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 rounded-lg dark:border-red-800">
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import type { AuthUser } from '../../../../types/dashboard'
|
|
3
3
|
import { describeAuthError, isLoginResponse, isTwoFactorChallenge, safeAuthRedirect, useAuth } from '../../../../functions/auth'
|
|
4
|
+
// Branding passes through to the card: an Iconify class for the mark and a short line above the title (stacksjs/stacks#3086).
|
|
5
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
6
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
4
7
|
|
|
5
8
|
const { login, verifyTwoFactorLogin } = useAuth()
|
|
6
9
|
const route = useRoute()
|
|
@@ -71,6 +74,8 @@ function restartLogin(): void {
|
|
|
71
74
|
|
|
72
75
|
<template>
|
|
73
76
|
<Login
|
|
77
|
+
:icon="icon()"
|
|
78
|
+
:eyebrow="eyebrow()"
|
|
74
79
|
:if="!challengeToken()"
|
|
75
80
|
@submit="handleLogin"
|
|
76
81
|
:isLoading="isLoading()"
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
const emit = defineEmits(['submit'])
|
|
5
5
|
const title = useReactiveProp<string>('title', 'Create an account')
|
|
6
6
|
const subtitle = useReactiveProp<string>('subtitle', 'Get started with your free account')
|
|
7
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
8
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
7
9
|
const isLoading = useReactiveProp<boolean>('isLoading', false)
|
|
8
10
|
const error = useReactiveProp<string>('error', '')
|
|
9
11
|
const showLogin = useReactiveProp<boolean>('showLogin', true)
|
|
@@ -98,7 +100,7 @@ function handleSubmit(): void {
|
|
|
98
100
|
})
|
|
99
101
|
}
|
|
100
102
|
</script>
|
|
101
|
-
<AuthCard :title="title()" :subtitle="subtitle()">
|
|
103
|
+
<AuthCard :title="title()" :subtitle="subtitle()" :icon="icon()" :eyebrow="eyebrow()">
|
|
102
104
|
|
|
103
105
|
<!-- Register Form -->
|
|
104
106
|
<div class="p-6 bg-white dark:bg-neutral-900 border border-neutral-200/60 rounded-2xl dark:border-neutral-800 shadow-black/5 shadow-xl dark:shadow-black/20">
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<script client>
|
|
2
2
|
import type { RegisterCredentials } from '../../../../types/dashboard'
|
|
3
3
|
import { describeAuthError, safeAuthRedirect, useAuth } from '../../../../functions/auth'
|
|
4
|
+
// Branding passes through to the card: an Iconify class for the mark and a short line above the title (stacksjs/stacks#3086).
|
|
5
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
6
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
4
7
|
|
|
5
8
|
const { register } = useAuth()
|
|
6
9
|
const route = useRoute()
|
|
@@ -38,6 +41,8 @@ async function handleRegister(credentials: RegisterCredentials): Promise<void> {
|
|
|
38
41
|
|
|
39
42
|
<template>
|
|
40
43
|
<Register
|
|
44
|
+
:icon="icon()"
|
|
45
|
+
:eyebrow="eyebrow()"
|
|
41
46
|
@submit="handleRegister"
|
|
42
47
|
:isLoading="isLoading()"
|
|
43
48
|
:error="error()"
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
const emit = defineEmits(['submit'])
|
|
17
17
|
const title = useReactiveProp<string>('title', 'Choose a new password')
|
|
18
18
|
const subtitle = useReactiveProp<string>('subtitle', 'Set the password you will use to sign in')
|
|
19
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
20
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
19
21
|
const isLoading = useReactiveProp<boolean>('isLoading', false)
|
|
20
22
|
const error = useReactiveProp<string>('error', '')
|
|
21
23
|
const success = useReactiveProp<boolean>('success', false)
|
|
@@ -43,7 +45,7 @@ function handleSubmit(): void {
|
|
|
43
45
|
}
|
|
44
46
|
</script>
|
|
45
47
|
|
|
46
|
-
<AuthCard :title="title()" :subtitle="subtitle()">
|
|
48
|
+
<AuthCard :title="title()" :subtitle="subtitle()" :icon="icon()" :eyebrow="eyebrow()">
|
|
47
49
|
|
|
48
50
|
<!-- Form Card -->
|
|
49
51
|
<div class="p-6 bg-white dark:bg-neutral-900 border border-neutral-200/60 rounded-2xl dark:border-neutral-800 shadow-black/5 shadow-xl dark:shadow-black/20">
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* instead of after someone has chosen and typed a new password twice.
|
|
13
13
|
*/
|
|
14
14
|
import { dashboardApi } from '../../../../functions/dashboard-api'
|
|
15
|
+
// Branding passes through to the card: an Iconify class for the mark and a short line above the title (stacksjs/stacks#3086).
|
|
16
|
+
const icon = useReactiveProp<string>('icon', 'i-hugeicons-cube')
|
|
17
|
+
const eyebrow = useReactiveProp<string>('eyebrow', '')
|
|
15
18
|
|
|
16
19
|
const route = useRoute()
|
|
17
20
|
|
|
@@ -85,6 +88,8 @@ effect(() => {
|
|
|
85
88
|
|
|
86
89
|
<template>
|
|
87
90
|
<ResetPassword
|
|
91
|
+
:icon="icon()"
|
|
92
|
+
:eyebrow="eyebrow()"
|
|
88
93
|
@submit="handleReset"
|
|
89
94
|
:checking="checking()"
|
|
90
95
|
:invalid="invalid()"
|
package/routes/dashboard.ts
CHANGED
|
@@ -182,6 +182,8 @@ route.get('/robots.txt', 'Actions/RobotsAction')
|
|
|
182
182
|
route.group({ prefix: '/ai', middleware: guarded('/ai') }, () => {
|
|
183
183
|
route.post('/ask', 'Actions/AI/AskAction')
|
|
184
184
|
route.post('/summary', 'Actions/AI/SummaryAction')
|
|
185
|
+
// Ghost-text completions for editors: `{ before, after?, kind?, context? }` -> `{ completion }`.
|
|
186
|
+
route.post('/complete', 'Actions/AI/CompleteAction')
|
|
185
187
|
})
|
|
186
188
|
|
|
187
189
|
// ============================================================================
|