@insitue/sdk 0.2.0 → 0.3.2
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/README.md +203 -0
- package/dist/capture-only.d.ts +26 -16
- package/dist/capture-only.js +1 -2
- package/dist/{chunk-62N4L6RA.js → chunk-YU5T67XL.js} +760 -68
- package/dist/index.d.ts +52 -25
- package/dist/index.js +26 -25
- package/package.json +1 -6
- package/dist/chunk-VRINS2SK.js +0 -1236
- package/dist/chunk-ZV3AVYBI.js +0 -400
- package/dist/overlay.d.ts +0 -6
- package/dist/overlay.js +0 -7
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# `@insitue/sdk`
|
|
2
|
+
|
|
3
|
+
The InSitue capture widget for browser apps. One component,
|
|
4
|
+
two sinks: ship captures to the InSitue Cloud (production
|
|
5
|
+
bug-reporting → autopilot → draft PR) or to a local
|
|
6
|
+
`@insitue/companion` (developer mode → `claude` in your terminal
|
|
7
|
+
acts on each pick).
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { InSitueCapture } from "@insitue/sdk";
|
|
11
|
+
|
|
12
|
+
// Dev: companion sink (no projectKey).
|
|
13
|
+
<InSitueCapture />
|
|
14
|
+
|
|
15
|
+
// Prod: cloud sink with your publishable project key.
|
|
16
|
+
<InSitueCapture projectKey="pk_..." />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Same widget. Same picker. Same screenshot pipeline. Only the
|
|
20
|
+
submit step changes.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -D @insitue/sdk
|
|
28
|
+
# or pnpm add -D @insitue/sdk
|
|
29
|
+
# or yarn add -D @insitue/sdk
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Dev mode (talk to claude in your terminal)
|
|
33
|
+
|
|
34
|
+
Mount with no props. The widget connects to a local companion
|
|
35
|
+
over a loopback WebSocket. A `claude` session running
|
|
36
|
+
[`/insitue:connect`](https://www.npmjs.com/package/@insitue/claude-plugin)
|
|
37
|
+
picks up each capture and edits the file you pointed at.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// app/layout.tsx (Next.js) — dev-gated so the chunk never
|
|
41
|
+
// ships in production.
|
|
42
|
+
import { InSitueCapture } from "@insitue/sdk";
|
|
43
|
+
|
|
44
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
45
|
+
return (
|
|
46
|
+
<html>
|
|
47
|
+
<body>
|
|
48
|
+
{children}
|
|
49
|
+
{process.env.NODE_ENV !== "production" && <InSitueCapture />}
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// src/main.tsx (Vite)
|
|
58
|
+
import { InSitueCapture } from "@insitue/sdk";
|
|
59
|
+
|
|
60
|
+
createRoot(document.getElementById("root")!).render(
|
|
61
|
+
<StrictMode>
|
|
62
|
+
<App />
|
|
63
|
+
{import.meta.env.DEV && <InSitueCapture />}
|
|
64
|
+
</StrictMode>,
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Production mode (cloud sink → autopilot → draft PR)
|
|
69
|
+
|
|
70
|
+
Pass your publishable `projectKey` (e.g. `pk_…`). The key is
|
|
71
|
+
Origin-pinned and quota-gated server-side, so it's safe to ship
|
|
72
|
+
in a public bundle.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<InSitueCapture projectKey={process.env.NEXT_PUBLIC_INSITUE_KEY!} />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
End users see a friendly "Report a problem" pill in the corner
|
|
79
|
+
of your app. Clicking it activates the picker; describing +
|
|
80
|
+
sending submits to your InSitue inbox.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Props
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
interface InSitueCaptureProps {
|
|
88
|
+
/** Publishable project key. Set → cloud sink. */
|
|
89
|
+
projectKey?: string;
|
|
90
|
+
/** Override the cloud ingest endpoint. */
|
|
91
|
+
endpoint?: string;
|
|
92
|
+
/** Take over delivery yourself. Wins over both projectKey
|
|
93
|
+
* and sink. */
|
|
94
|
+
onCapture?: (draft: IssueDraft, bundle: CaptureBundle) => void;
|
|
95
|
+
/** Explicit sink override (rarely needed — most callers rely
|
|
96
|
+
* on auto-detection). */
|
|
97
|
+
sink?: CaptureSink;
|
|
98
|
+
/** Force getDisplayMedia capture from mount. Dev/dogfood only. */
|
|
99
|
+
defaultPixelPerfect?: boolean;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Sink auto-detection
|
|
104
|
+
|
|
105
|
+
| `projectKey` | `sink` | Result |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| set | unset | Cloud sink (post to InSitue Cloud) |
|
|
108
|
+
| unset | unset | Companion sink (post to local WS, default port `5747`) |
|
|
109
|
+
| any | set | Use `sink` verbatim |
|
|
110
|
+
|
|
111
|
+
`onCapture` wins over everything when defined.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Bulletproof selection
|
|
116
|
+
|
|
117
|
+
Every pick the widget submits has a usable source location.
|
|
118
|
+
The picker walks React fiber `_debugSource` first (exact), then
|
|
119
|
+
the `data-insitu-source` attribute injected by
|
|
120
|
+
[`@insitue/sdk/babel`](#babel-plugin) (exact), then the nearest
|
|
121
|
+
owning component's source (approximate). If even that fails,
|
|
122
|
+
the widget refuses to send and asks the user to pick a parent
|
|
123
|
+
— claude never gets a meaningless selector-only pick.
|
|
124
|
+
|
|
125
|
+
The confidence chip is shown inline so users (and you, in
|
|
126
|
+
testing) can see exactly what's been resolved before they hit
|
|
127
|
+
Send.
|
|
128
|
+
|
|
129
|
+
## Babel plugin
|
|
130
|
+
|
|
131
|
+
Optional — only needed when your bundler doesn't expose React
|
|
132
|
+
fiber `_debugSource` (Vite, some Webpack setups). Adds a
|
|
133
|
+
`data-insitu-source="file:line:col"` attribute to every
|
|
134
|
+
intrinsic JSX element so source resolution stays exact.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
// vite.config.ts
|
|
138
|
+
import insituBabel from "@insitue/sdk/babel";
|
|
139
|
+
|
|
140
|
+
export default {
|
|
141
|
+
plugins: [
|
|
142
|
+
react({
|
|
143
|
+
babel: {
|
|
144
|
+
plugins: [[insituBabel, { root: __dirname }]],
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The `root` must match the project directory the companion is
|
|
152
|
+
scoped to (typically `__dirname` of `vite.config.ts`).
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## What's in a capture
|
|
157
|
+
|
|
158
|
+
Every send produces a `CaptureBundle`:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
interface CaptureBundle {
|
|
162
|
+
id: string; // unique per capture
|
|
163
|
+
target: { source, confidence, selector, componentStack };
|
|
164
|
+
screenshot?: { dataUrl, source: "rasterise" | "display-media" };
|
|
165
|
+
computedStyles: Record<string, string>;
|
|
166
|
+
tailwindClasses: string[];
|
|
167
|
+
userNote?: string; // the user's description
|
|
168
|
+
runtime: { url, route, console, network, errors };
|
|
169
|
+
viewport: { w, h, dpr, breakpoint };
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Cloud sink: this goes to `https://www.insitue.com/api/v1/capture`
|
|
174
|
+
with your `projectKey`. Companion sink: it goes to
|
|
175
|
+
`ws://127.0.0.1:5747` (the local companion's loopback WS) which
|
|
176
|
+
broadcasts to subscribed CLI/MCP listeners.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Going to production
|
|
181
|
+
|
|
182
|
+
The same `<InSitueCapture />` works in both modes — just pass
|
|
183
|
+
`projectKey` in production and your users get the SaaS theme
|
|
184
|
+
(warm, friendly) instead of the dev theme (dark, terminal-flavour).
|
|
185
|
+
A typical setup:
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
const PROJECT_KEY = process.env.NEXT_PUBLIC_INSITUE_KEY;
|
|
189
|
+
const IS_PROD = process.env.NODE_ENV === "production";
|
|
190
|
+
|
|
191
|
+
export default function InSitueWidget() {
|
|
192
|
+
if (IS_PROD && !PROJECT_KEY) return null;
|
|
193
|
+
return IS_PROD ? <InSitueCapture projectKey={PROJECT_KEY} /> : <InSitueCapture />;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Then drop `<InSitueWidget />` once in your app root.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT.
|
package/dist/capture-only.d.ts
CHANGED
|
@@ -1,37 +1,47 @@
|
|
|
1
1
|
import { IssueDraft, CaptureBundle } from '@insitue/capture-core';
|
|
2
2
|
|
|
3
|
+
/** Where captures go. Auto-detected from `projectKey` if omitted. */
|
|
4
|
+
type CaptureSink = {
|
|
5
|
+
kind: "cloud";
|
|
6
|
+
projectKey: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "companion";
|
|
10
|
+
port?: number;
|
|
11
|
+
};
|
|
3
12
|
interface CaptureOnlyOptions {
|
|
4
13
|
/**
|
|
5
14
|
* Publishable project key (e.g. `pk_…`). When set, captures POST
|
|
6
|
-
* to the InSitue cloud automatically —
|
|
7
|
-
*
|
|
8
|
-
* server-side) so it's safe to ship in
|
|
15
|
+
* to the InSitue cloud automatically — implies `sink: { kind:
|
|
16
|
+
* "cloud", projectKey }`. The key is publishable (Origin-pinned +
|
|
17
|
+
* quota-gated server-side) so it's safe to ship in production.
|
|
9
18
|
*/
|
|
10
19
|
projectKey?: string;
|
|
11
|
-
/**
|
|
12
|
-
* Ingest endpoint. Defaults to the InSitue cloud. Override only if
|
|
13
|
-
* you self-host the ingest service or proxy it from your own
|
|
14
|
-
* origin.
|
|
15
|
-
*/
|
|
20
|
+
/** Ingest endpoint (cloud sink). Defaults to the InSitue cloud. */
|
|
16
21
|
endpoint?: string;
|
|
17
22
|
/**
|
|
18
|
-
* Take over delivery yourself. Wins over `projectKey`
|
|
19
|
-
*
|
|
20
|
-
* `window.__insitu_capture__` (useful for prod
|
|
23
|
+
* Take over delivery yourself. Wins over `projectKey` AND `sink`.
|
|
24
|
+
* Default (neither set + no companion reachable): console + JSON
|
|
25
|
+
* download + `window.__insitu_capture__` (useful for prod
|
|
26
|
+
* validation).
|
|
21
27
|
*/
|
|
22
28
|
onCapture?: (draft: IssueDraft, bundle: CaptureBundle) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Override the sink explicitly. Use when auto-detection isn't
|
|
31
|
+
* right — e.g. you set a `projectKey` but want to ship to a local
|
|
32
|
+
* companion for testing. Most callers leave this undefined.
|
|
33
|
+
*/
|
|
34
|
+
sink?: CaptureSink;
|
|
23
35
|
/**
|
|
24
36
|
* Force the pixel-perfect (`getDisplayMedia`) path for every
|
|
25
37
|
* capture from mount. Costs a one-time tab-share permission per
|
|
26
38
|
* session in exchange for screenshots that are guaranteed to
|
|
27
39
|
* match what the user actually saw — bypasses every html-to-image
|
|
28
|
-
* quirk
|
|
29
|
-
*
|
|
30
|
-
* matters more than permission UX; leave off for prod end-users
|
|
31
|
-
* who shouldn't see a permission dialog uninvited.
|
|
40
|
+
* quirk. Use in dev/dogfood where capture quality matters more
|
|
41
|
+
* than the permission UX.
|
|
32
42
|
*/
|
|
33
43
|
defaultPixelPerfect?: boolean;
|
|
34
44
|
}
|
|
35
45
|
declare function mountCaptureOnly(opts?: CaptureOnlyOptions): () => void;
|
|
36
46
|
|
|
37
|
-
export { type CaptureOnlyOptions, mountCaptureOnly };
|
|
47
|
+
export { type CaptureOnlyOptions, type CaptureSink, mountCaptureOnly };
|