opencrater 0.2.4 → 1.0.0
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/LICENSE +38 -216
- package/README.md +169 -14
- package/dist/cli.js +19 -0
- package/dist/dismiss.js +3 -0
- package/dist/hook.js +6 -0
- package/dist/index.d.mts +209 -0
- package/dist/index.d.ts +209 -0
- package/dist/index.js +6 -0
- package/dist/index.mjs +6 -0
- package/dist/paint.js +9 -0
- package/package.json +35 -13
- package/cli.js +0 -416
package/LICENSE
CHANGED
|
@@ -1,216 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
(an example is provided in the Appendix below).
|
|
40
|
-
|
|
41
|
-
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
-
form, that is based on (or derived from) the Work and for which the
|
|
43
|
-
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
-
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
-
of this License, Derivative Works shall not include works that remain
|
|
46
|
-
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
-
the Work and Derivative Works thereof.
|
|
48
|
-
|
|
49
|
-
"Contribution" shall mean any work of authorship, including
|
|
50
|
-
the original version of the Work and any modifications or additions
|
|
51
|
-
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
-
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
-
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
-
means any form of electronic, verbal, or written communication sent
|
|
56
|
-
to the Licensor or its representatives, including but not limited to
|
|
57
|
-
communication on electronic mailing lists, source code control systems,
|
|
58
|
-
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
-
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
-
excluding communication that is conspicuously marked or otherwise
|
|
61
|
-
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
-
|
|
63
|
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
-
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
-
subsequently incorporated within the Work.
|
|
66
|
-
|
|
67
|
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
-
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
-
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
-
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
-
Work and such Derivative Works in Source or Object form.
|
|
73
|
-
|
|
74
|
-
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
-
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
-
(except as stated in this section) patent license to make, have made,
|
|
78
|
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
-
where such license applies only to those patent claims licensable
|
|
80
|
-
by such Contributor that are necessarily infringed by their
|
|
81
|
-
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
-
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
-
institute patent litigation against any entity (including a
|
|
84
|
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
-
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
-
or contributory patent infringement, then any patent licenses
|
|
87
|
-
granted to You under this License for that Work shall terminate
|
|
88
|
-
as of the date such litigation is filed.
|
|
89
|
-
|
|
90
|
-
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
-
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
-
modifications, and in Source or Object form, provided that You
|
|
93
|
-
meet the following conditions:
|
|
94
|
-
|
|
95
|
-
(a) You must give any other recipients of the Work or
|
|
96
|
-
Derivative Works a copy of this License; and
|
|
97
|
-
|
|
98
|
-
(b) You must cause any modified files to carry prominent notices
|
|
99
|
-
stating that You changed the files; and
|
|
100
|
-
|
|
101
|
-
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
-
that You distribute, all copyright, patent, trademark, and
|
|
103
|
-
attribution notices from the Source form of the Work,
|
|
104
|
-
excluding those notices that do not pertain to any part of
|
|
105
|
-
the Derivative Works; and
|
|
106
|
-
|
|
107
|
-
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
-
distribution, then any Derivative Works that You distribute must
|
|
109
|
-
include a readable copy of the attribution notices contained
|
|
110
|
-
within such NOTICE file, excluding those notices that do not
|
|
111
|
-
pertain to any part of the Derivative Works, in at least one
|
|
112
|
-
of the following places: within a NOTICE text file distributed
|
|
113
|
-
as part of the Derivative Works; within the Source form or
|
|
114
|
-
documentation, if provided along with the Derivative Works; or,
|
|
115
|
-
within a display generated by the Derivative Works, if and
|
|
116
|
-
wherever such third-party notices normally appear. The contents
|
|
117
|
-
of the NOTICE file are for informational purposes only and
|
|
118
|
-
do not modify the License. You may add Your own attribution
|
|
119
|
-
notices within Derivative Works that You distribute, alongside
|
|
120
|
-
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
-
that such additional attribution notices cannot be construed
|
|
122
|
-
as modifying the License.
|
|
123
|
-
|
|
124
|
-
You may add Your own copyright statement to Your modifications and
|
|
125
|
-
may provide additional or different license terms and conditions
|
|
126
|
-
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
-
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
-
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
-
the conditions stated in this License.
|
|
130
|
-
|
|
131
|
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
-
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
-
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
-
this License, without any additional terms or conditions.
|
|
135
|
-
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
-
the terms of any separate license agreement you may have executed
|
|
137
|
-
with Licensor regarding such Contributions.
|
|
138
|
-
|
|
139
|
-
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
-
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
-
except as required for reasonable and customary use in describing the
|
|
142
|
-
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
-
|
|
144
|
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
-
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
-
implied, including, without limitation, any warranties or conditions
|
|
149
|
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
-
appropriateness of using or redistributing the Work and assume any
|
|
152
|
-
risks associated with Your exercise of permissions under this License.
|
|
153
|
-
|
|
154
|
-
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
-
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
-
unless required by applicable law (such as deliberate and grossly
|
|
157
|
-
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
-
liable to You for damages, including any direct, indirect, special,
|
|
159
|
-
incidental, or consequential damages of any character arising as a
|
|
160
|
-
result of this License or out of the use or inability to use the
|
|
161
|
-
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
-
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
-
other commercial damages or losses), even if such Contributor
|
|
164
|
-
has been advised of the possibility of such damages.
|
|
165
|
-
|
|
166
|
-
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
-
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
-
or other liability obligations and/or rights consistent with this
|
|
170
|
-
License. However, in accepting such obligations, You may act only
|
|
171
|
-
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
-
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
-
defend, and hold each Contributor harmless for any liability
|
|
174
|
-
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
-
of your accepting any such warranty or additional liability.
|
|
176
|
-
|
|
177
|
-
END OF TERMS AND CONDITIONS
|
|
178
|
-
|
|
179
|
-
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
-
|
|
181
|
-
To apply the Apache License to your work, attach the following
|
|
182
|
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
-
replaced with your own identifying information. (Don't include
|
|
184
|
-
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
-
comment syntax for the file format. We also recommend that a
|
|
186
|
-
file or class name and description of purpose be included on the
|
|
187
|
-
same "printed page" as the copyright notice for easier
|
|
188
|
-
identification within third-party archives.
|
|
189
|
-
|
|
190
|
-
Copyright [yyyy] [name of copyright owner]
|
|
191
|
-
|
|
192
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
-
you may not use this file except in compliance with the License.
|
|
194
|
-
You may obtain a copy of the License at
|
|
195
|
-
|
|
196
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
-
|
|
198
|
-
Unless required by applicable law or agreed to in writing, software
|
|
199
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
-
See the License for the specific language governing permissions and
|
|
202
|
-
limitations under the License.
|
|
203
|
-
|
|
204
|
-
Copyright 2026 OpenCrater
|
|
205
|
-
|
|
206
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
207
|
-
you may not use this file except in compliance with the License.
|
|
208
|
-
You may obtain a copy of the License at
|
|
209
|
-
|
|
210
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
211
|
-
|
|
212
|
-
Unless required by applicable law or agreed to in writing, software
|
|
213
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
214
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
215
|
-
See the License for the specific language governing permissions and
|
|
216
|
-
limitations under the License.
|
|
1
|
+
OpenCrater SDK — Proprietary License
|
|
2
|
+
Copyright (c) 2026 OpenCrater. All rights reserved.
|
|
3
|
+
|
|
4
|
+
This software and its source code (the "Software"), including the published
|
|
5
|
+
package "@opencrater/sdk" and all of its contents, are the proprietary and
|
|
6
|
+
confidential property of OpenCrater.
|
|
7
|
+
|
|
8
|
+
PERMITTED USE
|
|
9
|
+
You are granted a limited, non-exclusive, non-transferable, revocable license
|
|
10
|
+
to INSTALL and RUN the Software, unmodified, solely as a dependency for the
|
|
11
|
+
purpose of integrating with the OpenCrater service. No other rights are granted.
|
|
12
|
+
|
|
13
|
+
PROHIBITED
|
|
14
|
+
Except to the extent this restriction is unenforceable under applicable law,
|
|
15
|
+
you may NOT, without the prior written permission of OpenCrater:
|
|
16
|
+
- copy, reproduce, or republish the Software or any portion of it;
|
|
17
|
+
- modify, adapt, translate, or create derivative works of the Software;
|
|
18
|
+
- reverse engineer, decompile, or disassemble the Software, or otherwise
|
|
19
|
+
attempt to derive its source, structure, algorithms, or techniques, except
|
|
20
|
+
to the limited extent such activity is expressly permitted by applicable
|
|
21
|
+
law notwithstanding this limitation;
|
|
22
|
+
- distribute, sublicense, sell, rent, lease, or otherwise make the Software
|
|
23
|
+
available to any third party;
|
|
24
|
+
- remove or alter any proprietary notices.
|
|
25
|
+
|
|
26
|
+
NO OPEN-SOURCE GRANT
|
|
27
|
+
The Software is NOT open source. Publication on a public registry (e.g. npm)
|
|
28
|
+
is solely to enable installation and does not place the Software in the public
|
|
29
|
+
domain or grant any license beyond the limited PERMITTED USE above.
|
|
30
|
+
|
|
31
|
+
NO WARRANTY
|
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
33
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
34
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
35
|
+
OPENCRATER BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM,
|
|
36
|
+
OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR ITS USE.
|
|
37
|
+
|
|
38
|
+
For licensing inquiries: opencrater.to
|
package/README.md
CHANGED
|
@@ -1,25 +1,180 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://opencrater.to/brand/green/logo-green.png" width="96" alt="OpenCrater logo" />
|
|
4
|
+
|
|
1
5
|
# opencrater
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
**AdSense for the terminal.** Tasteful, opt-in sponsor cards for CLI tools, MCP servers, and AI agents — the rendering engine that powers [OpenCrater](https://opencrater.to).
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/opencrater)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
A sponsor card renders at a natural pause in the session (a session edge), then auto-dismisses:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
╭─ terminal ──────────────────────────────────────────────
|
|
22
|
+
│
|
|
23
|
+
│ Sponsored · Vercel auto-dismiss 25s ✕
|
|
24
|
+
│
|
|
25
|
+
│ DEPLOY IN ONE COMMAND
|
|
26
|
+
│ Ship your app to 30+ edge regions in a single push.
|
|
27
|
+
│ Free tier — no credit card.
|
|
28
|
+
│
|
|
29
|
+
│ ▌ visit sponsor →
|
|
30
|
+
│
|
|
31
|
+
│ dismiss: click ✕ · npx opencrater x · ⚑ report
|
|
32
|
+
│
|
|
33
|
+
╰──────────────────────────────────────────────────────────
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> ▶ **See it live and interactive** (audio, media, real host chrome): <https://opencrater.to>
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## What is this?
|
|
41
|
+
|
|
42
|
+
OpenCrater lets the maintainers of command-line tools, MCP servers, and AI agents **earn revenue** by showing one small, clearly-labeled sponsor card at a natural break in a session — the terminal equivalent of an ad slot on a website. It's **opt-in**, **frequency-capped**, **privacy-preserving**, and **fail-silent**: it will never break, slow, or clutter the host tool.
|
|
43
|
+
|
|
44
|
+
This package, `opencrater`, is the **engine** — the same one used whether you enable cards with one command or integrate programmatically.
|
|
45
|
+
|
|
46
|
+
| If you are… | Go to |
|
|
47
|
+
|---|---|
|
|
48
|
+
| 👤 **A maintainer who just wants to earn** (no code) | [One command](#-one-command-no-code) |
|
|
49
|
+
| 🛠️ **A developer integrating programmatically** | [Programmatic use](#%EF%B8%8F-programmatic-use) |
|
|
50
|
+
| 🤖 **An AI agent / LLM setting this up** | [For AI agents](#-for-ai-agents) |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 👤 One command (no code)
|
|
55
|
+
|
|
56
|
+
Turn sponsor cards on for your own terminal — or wire them into a tool you publish — with the bundled CLI. No account required to *see* cards; a free publisher key (from <https://opencrater.to>) is what lets you *earn*.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx opencrater on # enable sponsor cards (Claude Code, Codex, Gemini CLI)
|
|
60
|
+
npx opencrater status # show what's installed
|
|
61
|
+
npx opencrater off # disable — removes only OpenCrater's own hooks
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
To earn as a publisher, register your package once at <https://opencrater.to>, then:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx opencrater on --key ock_your_publisher_key --package your-tool-name
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Every click on a sponsor card credits your account — you're on your way to monetizing your terminal tool.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🛠️ Programmatic use
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install opencrater
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { sponsor } from "opencrater";
|
|
82
|
+
|
|
83
|
+
// Call at a natural pause (e.g. after your CLI finishes a task).
|
|
84
|
+
// Fail-silent: never throws, hard-capped network timeout, suppressed
|
|
85
|
+
// in CI / non-TTY / opted-out environments.
|
|
86
|
+
await sponsor.show({
|
|
87
|
+
publisherKey: "ock_your_publisher_key",
|
|
88
|
+
packageName: "your-tool-name",
|
|
89
|
+
placement: "command-finished",
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Full surface:
|
|
94
|
+
|
|
95
|
+
| Method | Does |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `sponsor.show(opts)` | Fetch → render → report an impression. Resolves `true` if a card was shown. |
|
|
98
|
+
| `sponsor.fetch(opts)` | Fetch an ad **without** rendering. Resolves to the `Ad` or `null`. |
|
|
99
|
+
| `sponsor.preload(opts)` | Warm a local pool so later renders need zero network. Resolves to the count pooled. |
|
|
100
|
+
| `sponsor.renderFromPool(opts)` | Render a pooled ad with no network on the hot path. |
|
|
101
|
+
|
|
102
|
+
Also exported: `renderCard`, `renderAd`, `textCardForAd`, `detectImageProtocol`, `DEFAULT_CONFIG`, `HOOK_CATALOG`, `SDK_VERSION`, and full TypeScript types. ESM + CJS, types included, **zero runtime dependencies** (Node built-ins only).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 🤖 For AI agents
|
|
107
|
+
|
|
108
|
+
Concise, unambiguous setup for an autonomous agent integrating OpenCrater on a user's machine. Run these verbatim; everything is fail-silent and reversible.
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
GOAL: enable opt-in terminal sponsor cards (and, if monetizing, attribute to a publisher).
|
|
112
|
+
|
|
113
|
+
ENABLE (current user's CLIs — Claude Code, Codex, Gemini CLI):
|
|
114
|
+
npx -y opencrater on
|
|
115
|
+
|
|
116
|
+
ENABLE WITH ATTRIBUTION (publisher earns on clicks):
|
|
117
|
+
npx -y opencrater on --key <ock_publisher_key> --package <package-name>
|
|
118
|
+
|
|
119
|
+
STATUS / DISABLE:
|
|
120
|
+
npx -y opencrater status
|
|
121
|
+
npx -y opencrater off # removes ONLY OpenCrater's hooks; never touches others
|
|
122
|
+
|
|
123
|
+
PROGRAMMATIC (inside a Node tool you maintain):
|
|
124
|
+
import { sponsor } from "opencrater";
|
|
125
|
+
await sponsor.show({ publisherKey: "<ock_...>", packageName: "<name>", placement: "<event>" });
|
|
126
|
+
|
|
127
|
+
GUARANTEES (safe to rely on):
|
|
128
|
+
- Never throws; network calls hard-timeout (~500ms); suppressed in CI, non-TTY pipes, and when opted out.
|
|
129
|
+
- At most ONE card per frequency interval, machine-wide, across all sources.
|
|
130
|
+
- Renders only at session edges; auto-dismisses; respects NO_COLOR.
|
|
131
|
+
|
|
132
|
+
PRIVACY: only anonymized topic keywords are sent — never raw prompts, file paths, or secrets.
|
|
133
|
+
|
|
134
|
+
OPT OUT: `npx opencrater off` or set env `OPENCRATER_DISABLE=1`.
|
|
135
|
+
|
|
136
|
+
DO NOT: enable without the user's consent; present cards as the tool's own content; remove a user's opt-out.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## How it works & safety guarantees
|
|
142
|
+
|
|
143
|
+
- **Trigger, don't print.** Host hooks (Claude Code / Codex / Gemini CLI) fire at session edges; the SDK spawns its own painter that draws the card directly to the terminal, then clears it. The host never has to surface output.
|
|
144
|
+
- **Never breaks the host.** Every entry point is fail-silent. Serve requests have a hard timeout. A failure renders *nothing* rather than an error.
|
|
145
|
+
- **One card, capped.** A machine-wide frequency cap means at most one card per interval **across every OpenCrater source** — installing this next to a publisher's OpenCrater-enabled package never doubles ads.
|
|
146
|
+
- **Suppressed where inappropriate.** CI, non-interactive pipes, `NO_COLOR`, and opted-out machines get nothing.
|
|
147
|
+
- **Cross-platform.** macOS, Linux, and Windows (Windows Terminal) all render with full feature parity — card, audio, live countdown, clickable controls, clean teardown.
|
|
148
|
+
|
|
149
|
+
## Privacy
|
|
150
|
+
|
|
151
|
+
Personalization uses **anonymized topic keywords only** — never raw prompts, file contents, paths, environment variables, or secrets. The user can opt out at any time and the SDK records no PII.
|
|
152
|
+
|
|
153
|
+
## Opt out
|
|
4
154
|
|
|
5
155
|
```bash
|
|
6
|
-
npx opencrater
|
|
7
|
-
|
|
8
|
-
npx opencrater off # disable
|
|
156
|
+
npx opencrater off # or:
|
|
157
|
+
OPENCRATER_DISABLE=1 # env var, disables all rendering
|
|
9
158
|
```
|
|
10
159
|
|
|
11
|
-
|
|
160
|
+
## Configuration (env)
|
|
161
|
+
|
|
162
|
+
| Variable | Effect |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `OPENCRATER_DISABLE=1` | Disable all rendering. |
|
|
165
|
+
| `NO_COLOR` | Render without color (respected automatically). |
|
|
166
|
+
| `OPENCRATER_MUTE=1` | Never play ad audio. |
|
|
167
|
+
|
|
168
|
+
## Platform support
|
|
169
|
+
|
|
170
|
+
Node ≥ 18.17 on macOS, Linux, and Windows (Windows Terminal). Any tool — written in any language — can integrate via the [`opencrater`](https://www.npmjs.com/package/opencrater) installer (`npx opencrater on`).
|
|
12
171
|
|
|
13
|
-
|
|
172
|
+
---
|
|
14
173
|
|
|
15
|
-
|
|
174
|
+
<div align="center">
|
|
16
175
|
|
|
17
|
-
|
|
176
|
+
[**opencrater.to**](https://opencrater.to) · [Dashboard](https://opencrater.to/dashboard) · [Docs](https://opencrater.to/docs) · [FAQ](https://opencrater.to/faq)
|
|
18
177
|
|
|
19
|
-
|
|
20
|
-
website?" dialog — choose **Configure Trusted Domains → trust
|
|
21
|
-
api.opencrater.to** and it never asks again. (Dismissing with ✕ or
|
|
22
|
-
`npx opencrater x` never opens anything — it's handled locally.)
|
|
23
|
-
- **Codex**: asks once to trust newly installed hooks on its next launch —
|
|
24
|
-
approve to enable cards. This is Codex's own security model.
|
|
178
|
+
Proprietary — © OpenCrater. Published for installation only; see [LICENSE](./LICENSE). Not open source.
|
|
25
179
|
|
|
180
|
+
</div>
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';var crypto=require('crypto'),p=require('fs'),D=require('os'),l=require('path');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var p__namespace=/*#__PURE__*/_interopNamespace(p);var D__namespace=/*#__PURE__*/_interopNamespace(D);var l__namespace=/*#__PURE__*/_interopNamespace(l);var E=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(n,t)=>(typeof require<"u"?require:n)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});function ee(e=process.env){let n=e.XDG_CONFIG_HOME,t=n&&n.trim()!==""?n:l__namespace.join(D__namespace.homedir(),".config");return l__namespace.join(t,"opencrater")}function O(e=process.env){return l__namespace.join(ee(e),"state.json")}function U(){return {installId:crypto.randomUUID(),lastShownAt:0,optOut:false,disclosureShown:false,cachedConfig:null,configFetchedAt:0,pool:[],allowedPlacements:{},sessionTopics:[],integrations:[]}}function h(e){return typeof e=="number"&&Number.isFinite(e)}function te(e){if(typeof e!="object"||e===null)return null;let n=e;return !h(n.minIntervalSeconds)||!h(n.serveTimeoutMs)||!h(n.preloadPoolSize)||typeof n.killSwitch!="boolean"?null:{minIntervalSeconds:n.minIntervalSeconds,serveTimeoutMs:n.serveTimeoutMs,preloadPoolSize:n.preloadPoolSize,killSwitch:n.killSwitch,displayDurationSeconds:h(n.displayDurationSeconds)?n.displayDurationSeconds:25,minSdkVersion:typeof n.minSdkVersion=="string"?n.minSdkVersion:""}}function ne(e){if(!Array.isArray(e))return [];let n=[];for(let t of e){if(typeof t!="object"||t===null)continue;let o=t,r=o.ad;if(!h(o.renderBy)||typeof r!="object"||r===null||typeof r.impressionId!="string"||typeof r.clickUrl!="string"||typeof r.sponsorLabel!="string"||typeof r.creative!="object"||r.creative===null)continue;let s=r.creative;typeof s.title!="string"||typeof s.body!="string"||n.push({ad:{impressionId:r.impressionId,...typeof r.campaignId=="string"?{campaignId:r.campaignId}:{},clickUrl:r.clickUrl,sponsorLabel:r.sponsorLabel,creative:{format:"text",title:s.title,body:s.body,...typeof s.cta=="string"?{cta:s.cta}:{}}},renderBy:o.renderBy});}return n}function oe(e){if(typeof e!="object"||e===null||Array.isArray(e))return {};let n={};for(let[t,o]of Object.entries(e)){if(!Array.isArray(o))continue;let r=o.filter(s=>typeof s=="string"&&s.length<=64);n[t]=r.slice(0,64);}return n}function re(e){if(!Array.isArray(e))return [];let n=[];for(let t of e){if(typeof t!="object"||t===null)continue;let o=t;if(!(typeof o.topic!="string"||!h(o.at))&&(n.push({topic:o.topic.slice(0,32),at:o.at}),n.length>=24))break}return n}function se(e){if(!Array.isArray(e))return [];let n=[],t=new Set;for(let o of e){if(typeof o!="object"||o===null)continue;let r=o;if(typeof r.key!="string"||typeof r.package!="string"||r.key===""||r.package==="")continue;let s=`${r.package}\0${r.key}`;if(!t.has(s)&&(t.add(s),n.push({key:r.key,package:r.package}),n.length>=32))break}return n}function ie(e){let n=U();if(typeof e!="object"||e===null)return n;let t=e;return {installId:typeof t.installId=="string"&&t.installId.length>0?t.installId:n.installId,lastShownAt:h(t.lastShownAt)&&t.lastShownAt>=0?t.lastShownAt:0,optOut:t.optOut===true,disclosureShown:t.disclosureShown===true,cachedConfig:te(t.cachedConfig),allowedPlacements:oe(t.allowedPlacements),sessionTopics:re(t.sessionTopics),integrations:se(t.integrations),configFetchedAt:h(t.configFetchedAt)&&t.configFetchedAt>=0?t.configFetchedAt:0,pool:ne(t.pool)}}function A(e=process.env){let n=O(e);try{let t=p__namespace.readFileSync(n,"utf8"),o=JSON.parse(t);return ie(o)}catch{let t=U();try{T(t,e);}catch{}return t}}function T(e,n=process.env){let t=O(n),o=l__namespace.dirname(t);p__namespace.mkdirSync(o,{recursive:true});let r=l__namespace.join(o,`.state.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);p__namespace.writeFileSync(r,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,"utf8");let s=new Set(["EPERM","EACCES","EBUSY","EEXIST"]);for(let i=0;;i++)try{p__namespace.renameSync(r,t);return}catch(m){let a=m.code??"";if(i>=4||!s.has(a)){try{p__namespace.rmSync(r,{force:!0});}catch{}if(i>=4)return;throw m}try{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,15*(i+1));}catch{}}}function w(e,n=process.env){let t={...A(n),...e};return T(t,n),t}var J={claude_code:["SessionStart","Stop","SessionEnd","Notification"],codex:["Stop"],openclaw:[],gemini_cli:["AfterAgent","SessionStart","SessionEnd"],copilot_cli:["agentStop","sessionStart","sessionEnd","notification"],generic:["SessionStart","Stop"]};var k=["claude_code","codex","gemini_cli","copilot_cli"];function b(e){return e.includes("opencrater-hook")||e.includes("@opencrater/sdk")}function ae(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function V(e,n){return b(e)&&new RegExp(`--package ['"]?${ae(n)}['"]?`).test(e)}function M(e){return /^[A-Za-z0-9@_./:-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}var L='"$HOME/.config/opencrater/runtime/node_modules/opencrater/dist/hook.js"',z="%USERPROFILE%\\.config\\opencrater\\runtime\\node_modules\\opencrater\\dist\\hook.js",G="$env:USERPROFILE\\.config\\opencrater\\runtime\\node_modules\\opencrater\\dist\\hook.js",ce=()=>process.platform==="win32";function H(e,n,t,o){let r=`--placement ${n} --key ${M(t)} --package ${M(o)} --host ${e}`;return `{ if [ -f ${L} ]; then node ${L} ${r}; else npx -y -p opencrater opencrater-hook ${r}; fi; } 2>/dev/null || true`}function le(e,n,t,o){let r=`--placement ${n} --key "${t}" --package "${o}" --host ${e}`;return `if exist "${z}" (node "${z}" ${r}) else (npx -y -p opencrater opencrater-hook ${r}) 2>nul`}function ue(e,n,t,o){let r=`--placement ${n} --key '${t}' --package '${o}' --host ${e}`;return `try { if (Test-Path "${G}") { node "${G}" ${r} } else { npx -y -p opencrater opencrater-hook ${r} } } catch {}`}function K(e,n,t,o){return ce()?le(e,n,t,o):H(e,n,t,o)}function W(e,n){let t=D__namespace.homedir();switch(e){case "claude_code":{let o=n.CLAUDE_CONFIG_DIR;return o&&o.trim()!==""?o:l__namespace.join(t,".claude")}case "codex":{let o=n.CODEX_HOME;return o&&o.trim()!==""?o:l__namespace.join(t,".codex")}case "gemini_cli":return l__namespace.join(t,".gemini");case "copilot_cli":{let o=n.COPILOT_HOME;return o&&o.trim()!==""?o:l__namespace.join(t,".copilot")}default:return l__namespace.join(t,".opencrater-unknown")}}function v(e,n=process.env){let t=W(e,n);switch(e){case "claude_code":return l__namespace.join(t,"settings.json");case "codex":return l__namespace.join(t,"hooks.json");case "gemini_cli":return l__namespace.join(t,"settings.json");case "copilot_cli":return l__namespace.join(t,"hooks","hooks.json");default:return l__namespace.join(t,"hooks.json")}}function pe(e,n=process.env){try{return p__namespace.existsSync(W(e,n))}catch{return false}}function I(e=process.env){return k.filter(n=>pe(n,e))}function $(e){let n;try{n=p__namespace.readFileSync(e,"utf8");}catch{return {}}let t=JSON.parse(n);if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`${e} is not a JSON object`);return t}function j(e,n){let t=l__namespace.dirname(e);p__namespace.mkdirSync(t,{recursive:true});let o=l__namespace.join(t,`.${l__namespace.basename(e)}.${process.pid}.tmp`);p__namespace.writeFileSync(o,JSON.stringify(n,null,2)+`
|
|
4
|
+
`,"utf8"),p__namespace.renameSync(o,e);}function de(e,n){return Array.isArray(e.hooks)&&e.hooks.some(t=>typeof t.command=="string"&&V(t.command,n))}function ge(e,n,t,o){let r=v(e),s=$(r),i=s.hooks&&typeof s.hooks=="object"?s.hooks:{};if(o.every(a=>{let u=K(e,a,n,t);return (Array.isArray(i[a])?i[a]:[]).some(c=>Array.isArray(c.hooks)&&c.hooks.some(g=>g.command===u))}))return "nochange";for(let a of o){let c=(Array.isArray(i[a])?i[a]:[]).filter(g=>!de(g,t));c.push({matcher:"",hooks:[{type:"command",command:K(e,a,n,t)}]}),i[a]=c;}return s.hooks=i,j(r,s),"wrote"}function fe(e,n){return [e.bash,e.powershell,e.command].some(t=>typeof t=="string"&&V(t,n))}function me(e,n,t,o){let r=v(e),s=$(r);typeof s.version!="number"&&(s.version=1);let i=s.hooks&&typeof s.hooks=="object"?s.hooks:{};if(o.every(a=>{let u=H(e,a,n,t);return (Array.isArray(i[a])?i[a]:[]).some(c=>c.bash===u)}))return "nochange";for(let a of o){let c=(Array.isArray(i[a])?i[a]:[]).filter(g=>!fe(g,t));c.push({type:"command",bash:H(e,a,n,t),powershell:ue(e,a,n,t),timeoutSec:5}),i[a]=c;}return s.hooks=i,j(r,s),"wrote"}function C(e){return [...J[e]]}function R(e,n,t){let o=C(e);return o.length===0?"nochange":e==="copilot_cli"?me(e,n,t,o):ge(e,n,t,o)}function N(e,n,t=process.env){return I(t).map(o=>{try{let r=R(o,e,n);return {host:o,status:r,events:C(o)}}catch(r){return {host:o,status:"error",events:[],error:r.message}}})}function P(e=process.env){let n=[];for(let t of k){let o;try{o=$(v(t,e));}catch{continue}let r=o.hooks;if(!(!r||typeof r!="object"))for(let[s,i]of Object.entries(r))for(let m of Array.isArray(i)?i:[]){let a=m,u=Array.isArray(a.hooks)?a.hooks.find(d=>typeof d.command=="string"&&b(d.command))?.command:void 0,c=[a.bash,a.command,a.powershell].find(d=>typeof d=="string"&&b(d)),g=u??c;g&&n.push({host:t,event:s,command:g});}}return n}function q(e=process.env){let n=0;for(let t of k){let o=v(t,e),r;try{r=$(o);}catch{continue}let s=r.hooks;if(!s||typeof s!="object")continue;let i=s,m=false;for(let a of Object.keys(i)){let u=Array.isArray(i[a])?i[a]:[],c=u.filter(g=>{let d=g,F=Array.isArray(d.hooks)&&d.hooks.some(S=>typeof S.command=="string"&&b(S.command))||[d.bash,d.powershell,d.command].some(S=>typeof S=="string"&&b(S));return F&&n++,!F});c.length!==u.length&&(m=true,c.length>0?i[a]=c:delete i[a]);}if(m)try{let a=Object.keys(r).filter(c=>c!=="version"&&c!=="hooks"),u=t==="copilot_cli"||t==="codex";Object.keys(i).length===0&&a.length===0&&u?p__namespace.rmSync(o,{force:!0}):j(o,r);}catch{}}return n}var x="1.0.0";function Q(e){let n=new Map,t=[];for(let o=0;o<e.length;o++){let r=e[o];if(r!==void 0)if(r.startsWith("--")){let s=r.indexOf("=");if(s!==-1)n.set(r.slice(2,s),r.slice(s+1));else {let i=e[o+1];i!==void 0&&!i.startsWith("--")?(n.set(r.slice(2),i),o++):n.set(r.slice(2),"true");}}else t.push(r);}return {flags:n,rest:t}}function Y(e,n){let t=A();t.integrations.some(o=>o.key===e&&o.package===n)||w({integrations:[...t.integrations,{key:e,package:n}].slice(-32)});}function _(e,n){if(e.length===0){console.log(`No supported AI CLIs detected yet \u2014 OpenCrater will wire ${n} automatically the moment you install one (it re-checks once a day).`);return}console.log(`OpenCrater wired ${n} into:`);for(let t of e)if(t.status==="error")console.log(` \u2717 ${t.host}: ${t.error}`);else {let o=t.status==="nochange"?" \u2014 already set up":"";console.log(` \u2022 ${t.host} (${t.events.join(", ")})${o}`);}}function he(){return w({optOut:true}),console.log("OpenCrater sponsor messages are now OFF for this machine."),console.log("Re-enable any time with: npx opencrater on"),0}function ye(e){let{flags:n}=Q(e),t=n.get("key"),o=n.get("package");return w({optOut:false}),t&&o?(Y(t,o),_(N(t,o),o)):console.log("OpenCrater sponsor messages are now ON for this machine."),console.log("Opt out any time with: npx opencrater off"),0}function ke(){let e=A(),n=e.lastShownAt>0?new Date(e.lastShownAt).toISOString():"never";console.log(`opencrater v${x}`),console.log(` state file: ${O()}`),console.log(` install id: ${e.installId}`),console.log(` opted out: ${e.optOut?"yes":"no"}`),console.log(` last shown: ${n}`),console.log(` pooled ads: ${e.pool.length}`),console.log(` hosts found: ${I().join(", ")||"(none)"}`),console.log(` integrations: ${e.integrations.map(o=>o.package).join(", ")||"(none)"}`);let t=P();return console.log(` wired hooks: ${t.length}`),0}function Se(e){let{flags:n}=Q(e),t=n.get("key"),o=n.get("package");if(!t||!o)return console.error("Usage: opencrater hooks install --key <publisherKey> --package <name> [--host <host>]"),1;Y(t,o);let r=n.get("host");if(r&&r!=="true"){if(!k.includes(r))return console.error(`Unknown host "${r}". Supported: ${k.join(", ")}`),1;let s=r;try{let i=R(s,t,o);_([{host:s,status:i,events:C(s)}],o);}catch(i){return console.error(`Could not wire ${s}: ${i.message}`),1}}else _(N(t,o),o);return console.log("Remove with: npx opencrater hooks uninstall"),0}function we(){let e=q();return w({integrations:[]}),console.log(e>0?`Removed ${e} OpenCrater hook${e===1?"":"s"} across all hosts.`:"No OpenCrater hooks installed."),0}function be(){let e=P();if(e.length===0)return console.log("No OpenCrater hooks installed."),0;for(let n of e)console.log(`${n.host} ${n.event}: ${n.command}`);return 0}function X(){return console.log(`opencrater v${x} \u2014 OpenCrater sponsor messages
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
opencrater on [--key <ock_\u2026> --package <name>]
|
|
8
|
+
Opt in; with a key+package, auto-wire every AI CLI
|
|
9
|
+
installed (Claude Code, Codex, Gemini CLI, Copilot CLI)
|
|
10
|
+
and re-wire any host you install later.
|
|
11
|
+
opencrater off Opt out of sponsor messages on this machine
|
|
12
|
+
opencrater status Show install id, opt-out state, detected hosts
|
|
13
|
+
opencrater hooks install --key <ock_\u2026> --package <name> [--host <host>]
|
|
14
|
+
(Re)install hooks \u2014 all detected hosts, or one --host
|
|
15
|
+
opencrater hooks uninstall Remove all OpenCrater hooks (every host)
|
|
16
|
+
opencrater hooks list List installed OpenCrater hooks
|
|
17
|
+
|
|
18
|
+
Hosts: ${k.join(", ")}
|
|
19
|
+
Environment: OPENCRATER_DISABLE=1 disables everything; NO_COLOR respected.`),0}function Oe(e){let[n,...t]=e;switch(n){case "off":return he();case "on":return ye(t);case "status":return ke();case "hooks":{let[o,...r]=t;switch(o){case "install":return Se(r);case "uninstall":return we();case "list":return be();default:return console.error("Usage: opencrater hooks <install|uninstall|list>"),1}}case "version":case "--version":case "-v":return console.log(x),0;case void 0:case "help":case "--help":case "-h":return X();default:return console.error(`Unknown command: ${n}`),X(),1}}if(typeof E<"u"&&typeof module<"u"&&E.main===module)try{process.exitCode=Oe(process.argv.slice(2));}catch(e){console.error(`opencrater: ${e.message}`),process.exitCode=1;}exports.runCli=Oe;
|
package/dist/dismiss.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';var fs=require('fs'),os=require('os'),t=require('path');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var t__namespace=/*#__PURE__*/_interopNamespace(t);var i=(n,o)=>()=>(n&&(o=n(n=0)),o);var c=(n,o)=>()=>(o||n((o={exports:{}}).exports,o),o.exports);var r=i(()=>{});var s=i(()=>{});function a(n,o=process.env){let e=o.OPENCRATER_API_ORIGIN;return (n??(e&&e.trim()!==""?e:p)).replace(/\/+$/,"")}var p,l=i(()=>{r();s();p="https://api.opencrater.to";});var S=c(()=>{l();async function g(){let n=t__namespace.join(os.homedir(),".config","opencrater"),o=t__namespace.join(n,"painter.lock"),e={};try{e=JSON.parse(fs.readFileSync(o,"utf8"));}catch{console.log("opencrater: no sponsor card is on screen.");return}try{fs.mkdirSync(n,{recursive:!0}),fs.writeFileSync(t__namespace.join(n,"dismiss.signal"),JSON.stringify({impressionId:e.impressionId,at:Date.now()}));}catch{}if(e.dismissUrl)try{await fetch(e.dismissUrl,{signal:AbortSignal.timeout(1e3)});}catch{}if(e.impressionId)try{await fetch(`${a()}/x/${e.impressionId}`,{signal:AbortSignal.timeout(2500)});}catch{}if(e.pid&&e.pid>1)try{process.kill(e.pid,"SIGTERM");}catch{}console.log("opencrater: ad dismissed \u2014 feedback recorded."),console.log(" changed your mind? npx opencrater show");}g().finally(()=>{setTimeout(()=>process.exit(0),50).unref?.();});});var dismiss = S();
|
|
3
|
+
module.exports=dismiss;
|
package/dist/hook.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';var child_process=require('child_process'),l=require('fs'),E=require('os'),d=require('path'),crypto=require('crypto');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var l__namespace=/*#__PURE__*/_interopNamespace(l);var E__namespace=/*#__PURE__*/_interopNamespace(E);var d__namespace=/*#__PURE__*/_interopNamespace(d);var O=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var C={minIntervalSeconds:600,serveTimeoutMs:2500,preloadPoolSize:3,killSwitch:false,displayDurationSeconds:25,minSdkVersion:""},_={claude_code:["SessionStart","Stop","SessionEnd","Notification"],codex:["Stop"],openclaw:[],gemini_cli:["AfterAgent","SessionStart","SessionEnd"],copilot_cli:["agentStop","sessionStart","sessionEnd","notification"],generic:["SessionStart","Stop"]};var T="1.0.0";var ke="https://api.opencrater.to";function N(e,t=process.env){let n=t.OPENCRATER_API_ORIGIN;return ((n&&n.trim()!==""?n:ke)).replace(/\/+$/,"")}function m(...e){try{if(process.env.OPENCRATER_DEBUG!=="1")return;console.error("[opencrater]",...e);try{let t=O("os"),n=O("fs"),o=O("path");n.appendFileSync(o.join(t.homedir(),".config","opencrater","hook.log"),`${new Date().toISOString()} [opencrater] ${e.map(r=>String(r)).join(" ")}
|
|
3
|
+
`);}catch{}}catch{}}function P(e){return typeof e=="number"&&Number.isFinite(e)}function we(e){let t=C;if(typeof e!="object"||e===null)return {...t};let n=e;return {minIntervalSeconds:P(n.minIntervalSeconds)?n.minIntervalSeconds:t.minIntervalSeconds,serveTimeoutMs:P(n.serveTimeoutMs)?n.serveTimeoutMs:t.serveTimeoutMs,preloadPoolSize:P(n.preloadPoolSize)?n.preloadPoolSize:t.preloadPoolSize,killSwitch:n.killSwitch===true,displayDurationSeconds:P(n.displayDurationSeconds)?n.displayDurationSeconds:t.displayDurationSeconds,minSdkVersion:typeof n.minSdkVersion=="string"?n.minSdkVersion:t.minSdkVersion}}async function Y(e,t,n,o){try{let r=await fetch(`${e}${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(o)});return r.ok?await r.json():(m(`POST ${t} -> HTTP ${r.status}`),null)}catch(r){return m(`POST ${t} failed:`,r),null}}function Ee(e,t){let n=e.host??"generic";return {publisherKey:e.publisherKey,packageName:e.packageName,placement:e.placement,host:n,sdkVersion:T,installId:t.installId,os:process.platform,termProgram:process.env.TERM_PROGRAM??void 0,topics:t.topics&&t.topics.length>0?t.topics:void 0}}async function z(e,t){let n=await Y(t.origin,"/v1/serve",Ee(e,t),t.timeoutMs);if(typeof n!="object"||n===null)return null;let o=n;if(typeof o.fill!="boolean")return null;let r={fill:o.fill,fallback:o.fallback??null,config:we(o.config),...Array.isArray(o.allowedPlacements)?{allowedPlacements:o.allowedPlacements.filter(i=>typeof i=="string")}:{}};return o.ad!==void 0&&o.ad!==null&&(r.ad=o.ad),r}function $(e,t){return Y(t.origin,"/v1/events/impression",{impressionId:e},t.timeoutMs).then(()=>{}).catch(()=>{})}function W(e){let t={sponsorLabel:e.sponsorLabel,title:e.creative.title,body:e.creative.body,url:e.clickUrl};return e.creative.cta!==void 0&&(t.cta=e.creative.cta),t}function X(e){return {sponsorLabel:"",title:e.title,body:e.body,url:e.url}}function M(e){let t=W(e),n=e.creative;switch(n.format){case "image":case "gif":return {...t,body:n.textFallback??t.body};case "video":return {...t,body:n.textFallback??t.body,cta:t.cta??"\u25B6 Watch"};case "audio":return {...t,body:n.textFallback??t.body,cta:t.cta??"\u{1F50A} Listen"};default:return t}}function A(e=process.env){let t=e.XDG_CONFIG_HOME,n=t&&t.trim()!==""?t:d__namespace.join(E__namespace.homedir(),".config");return d__namespace.join(n,"opencrater")}function Z(e=process.env){return d__namespace.join(A(e),"state.json")}function Q(){return {installId:crypto.randomUUID(),lastShownAt:0,optOut:false,disclosureShown:false,cachedConfig:null,configFetchedAt:0,pool:[],allowedPlacements:{},sessionTopics:[],integrations:[]}}function k(e){return typeof e=="number"&&Number.isFinite(e)}function Oe(e){if(typeof e!="object"||e===null)return null;let t=e;return !k(t.minIntervalSeconds)||!k(t.serveTimeoutMs)||!k(t.preloadPoolSize)||typeof t.killSwitch!="boolean"?null:{minIntervalSeconds:t.minIntervalSeconds,serveTimeoutMs:t.serveTimeoutMs,preloadPoolSize:t.preloadPoolSize,killSwitch:t.killSwitch,displayDurationSeconds:k(t.displayDurationSeconds)?t.displayDurationSeconds:25,minSdkVersion:typeof t.minSdkVersion=="string"?t.minSdkVersion:""}}function Te(e){if(!Array.isArray(e))return [];let t=[];for(let n of e){if(typeof n!="object"||n===null)continue;let o=n,r=o.ad;if(!k(o.renderBy)||typeof r!="object"||r===null||typeof r.impressionId!="string"||typeof r.clickUrl!="string"||typeof r.sponsorLabel!="string"||typeof r.creative!="object"||r.creative===null)continue;let i=r.creative;typeof i.title!="string"||typeof i.body!="string"||t.push({ad:{impressionId:r.impressionId,...typeof r.campaignId=="string"?{campaignId:r.campaignId}:{},clickUrl:r.clickUrl,sponsorLabel:r.sponsorLabel,creative:{format:"text",title:i.title,body:i.body,...typeof i.cta=="string"?{cta:i.cta}:{}}},renderBy:o.renderBy});}return t}function Ie(e){if(typeof e!="object"||e===null||Array.isArray(e))return {};let t={};for(let[n,o]of Object.entries(e)){if(!Array.isArray(o))continue;let r=o.filter(i=>typeof i=="string"&&i.length<=64);t[n]=r.slice(0,64);}return t}function Ce(e){if(!Array.isArray(e))return [];let t=[];for(let n of e){if(typeof n!="object"||n===null)continue;let o=n;if(!(typeof o.topic!="string"||!k(o.at))&&(t.push({topic:o.topic.slice(0,32),at:o.at}),t.length>=24))break}return t}function Ae(e){if(!Array.isArray(e))return [];let t=[],n=new Set;for(let o of e){if(typeof o!="object"||o===null)continue;let r=o;if(typeof r.key!="string"||typeof r.package!="string"||r.key===""||r.package==="")continue;let i=`${r.package}\0${r.key}`;if(!n.has(i)&&(n.add(i),t.push({key:r.key,package:r.package}),t.length>=32))break}return t}function _e(e){let t=Q();if(typeof e!="object"||e===null)return t;let n=e;return {installId:typeof n.installId=="string"&&n.installId.length>0?n.installId:t.installId,lastShownAt:k(n.lastShownAt)&&n.lastShownAt>=0?n.lastShownAt:0,optOut:n.optOut===true,disclosureShown:n.disclosureShown===true,cachedConfig:Oe(n.cachedConfig),allowedPlacements:Ie(n.allowedPlacements),sessionTopics:Ce(n.sessionTopics),integrations:Ae(n.integrations),configFetchedAt:k(n.configFetchedAt)&&n.configFetchedAt>=0?n.configFetchedAt:0,pool:Te(n.pool)}}function D(e=process.env){let t=Z(e);try{let n=l__namespace.readFileSync(t,"utf8"),o=JSON.parse(n);return _e(o)}catch{let n=Q();try{y(n,e);}catch{}return n}}function y(e,t=process.env){let n=Z(t),o=d__namespace.dirname(n);l__namespace.mkdirSync(o,{recursive:true});let r=d__namespace.join(o,`.state.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);l__namespace.writeFileSync(r,JSON.stringify(e,null,2)+`
|
|
4
|
+
`,"utf8");let i=new Set(["EPERM","EACCES","EBUSY","EEXIST"]);for(let s=0;;s++)try{l__namespace.renameSync(r,n);return}catch(g){let a=g.code??"";if(s>=4||!i.has(a)){try{l__namespace.rmSync(r,{force:!0});}catch{}if(s>=4)return;throw g}try{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,15*(s+1));}catch{}}}var Pe=300*1e3;function ve(){return d__namespace.join(A(),"blocked-ads.json")}function j(){return d__namespace.join(A(),"recent-renders.json")}function xe(){return d__namespace.join(A(),"reported-ads.json")}function ee(e,t){let n={};for(let[o,r]of Object.entries(e))typeof r=="number"&&Number.isFinite(r)&&r>t&&(n[o]=r);return n}function Ne(e){try{let t=JSON.parse(l__namespace.readFileSync(ve(),"utf8"));return ee(t&&typeof t=="object"?t:{},e)}catch{return {}}}function $e(){try{let e=JSON.parse(l__namespace.readFileSync(xe(),"utf8"));return e&&typeof e=="object"?e:{}}catch{return {}}}function Me(e){return e?$e()[e]!==void 0:false}function F(e,t=Date.now()){return e?Ne(t)[e]!==void 0||Me(e):false}function te(e){try{let t=JSON.parse(l__namespace.readFileSync(j(),"utf8"));return ee(t&&typeof t=="object"?t:{},e)}catch{return {}}}function L(e,t=Date.now()){if(e)try{let n=te(t);n[e]=t+Pe,l__namespace.mkdirSync(d__namespace.dirname(j()),{recursive:!0}),l__namespace.writeFileSync(j(),JSON.stringify(n));}catch{}}function H(e,t=Date.now()){return e?te(t)[e]!==void 0:false}function De(e,t){return e.filter(n=>n.renderBy>t)}function U(e,t){let n=De(e.pool,t),o=n.shift();return {ad:o?o.ad:null,pool:n}}var je=["claude_code","codex","gemini_cli","copilot_cli"];function Fe(e){return e.includes("opencrater-hook")||e.includes("@opencrater/sdk")}function Le(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ae(e,t){return Fe(e)&&new RegExp(`--package ['"]?${Le(t)}['"]?`).test(e)}function ne(e){return /^[A-Za-z0-9@_./:-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}var re='"$HOME/.config/opencrater/runtime/node_modules/opencrater/dist/hook.js"',oe="%USERPROFILE%\\.config\\opencrater\\runtime\\node_modules\\opencrater\\dist\\hook.js",ie="$env:USERPROFILE\\.config\\opencrater\\runtime\\node_modules\\opencrater\\dist\\hook.js",He=()=>process.platform==="win32";function B(e,t,n,o){let r=`--placement ${t} --key ${ne(n)} --package ${ne(o)} --host ${e}`;return `{ if [ -f ${re} ]; then node ${re} ${r}; else npx -y -p opencrater opencrater-hook ${r}; fi; } 2>/dev/null || true`}function Ue(e,t,n,o){let r=`--placement ${t} --key "${n}" --package "${o}" --host ${e}`;return `if exist "${oe}" (node "${oe}" ${r}) else (npx -y -p opencrater opencrater-hook ${r}) 2>nul`}function Be(e,t,n,o){let r=`--placement ${t} --key '${n}' --package '${o}' --host ${e}`;return `try { if (Test-Path "${ie}") { node "${ie}" ${r} } else { npx -y -p opencrater opencrater-hook ${r} } } catch {}`}function se(e,t,n,o){return He()?Ue(e,t,n,o):B(e,t,n,o)}function le(e,t){let n=E__namespace.homedir();switch(e){case "claude_code":{let o=t.CLAUDE_CONFIG_DIR;return o&&o.trim()!==""?o:d__namespace.join(n,".claude")}case "codex":{let o=t.CODEX_HOME;return o&&o.trim()!==""?o:d__namespace.join(n,".codex")}case "gemini_cli":return d__namespace.join(n,".gemini");case "copilot_cli":{let o=t.COPILOT_HOME;return o&&o.trim()!==""?o:d__namespace.join(n,".copilot")}default:return d__namespace.join(n,".opencrater-unknown")}}function ue(e,t=process.env){let n=le(e,t);switch(e){case "claude_code":return d__namespace.join(n,"settings.json");case "codex":return d__namespace.join(n,"hooks.json");case "gemini_cli":return d__namespace.join(n,"settings.json");case "copilot_cli":return d__namespace.join(n,"hooks","hooks.json");default:return d__namespace.join(n,"hooks.json")}}function Je(e,t=process.env){try{return l__namespace.existsSync(le(e,t))}catch{return false}}function Ge(e=process.env){return je.filter(t=>Je(t,e))}function pe(e){let t;try{t=l__namespace.readFileSync(e,"utf8");}catch{return {}}let n=JSON.parse(t);if(typeof n!="object"||n===null||Array.isArray(n))throw new Error(`${e} is not a JSON object`);return n}function fe(e,t){let n=d__namespace.dirname(e);l__namespace.mkdirSync(n,{recursive:true});let o=d__namespace.join(n,`.${d__namespace.basename(e)}.${process.pid}.tmp`);l__namespace.writeFileSync(o,JSON.stringify(t,null,2)+`
|
|
5
|
+
`,"utf8"),l__namespace.renameSync(o,e);}function Ke(e,t){return Array.isArray(e.hooks)&&e.hooks.some(n=>typeof n.command=="string"&&ae(n.command,t))}function Ve(e,t,n,o){let r=ue(e),i=pe(r),s=i.hooks&&typeof i.hooks=="object"?i.hooks:{};if(o.every(a=>{let u=se(e,a,t,n);return (Array.isArray(s[a])?s[a]:[]).some(p=>Array.isArray(p.hooks)&&p.hooks.some(c=>c.command===u))}))return "nochange";for(let a of o){let p=(Array.isArray(s[a])?s[a]:[]).filter(c=>!Ke(c,n));p.push({matcher:"",hooks:[{type:"command",command:se(e,a,t,n)}]}),s[a]=p;}return i.hooks=s,fe(r,i),"wrote"}function Ye(e,t){return [e.bash,e.powershell,e.command].some(n=>typeof n=="string"&&ae(n,t))}function ze(e,t,n,o){let r=ue(e),i=pe(r);typeof i.version!="number"&&(i.version=1);let s=i.hooks&&typeof i.hooks=="object"?i.hooks:{};if(o.every(a=>{let u=B(e,a,t,n);return (Array.isArray(s[a])?s[a]:[]).some(p=>p.bash===u)}))return "nochange";for(let a of o){let p=(Array.isArray(s[a])?s[a]:[]).filter(c=>!Ye(c,n));p.push({type:"command",bash:B(e,a,t,n),powershell:Be(e,a,t,n),timeoutSec:5}),s[a]=p;}return i.hooks=s,fe(r,i),"wrote"}function de(e){return [..._[e]]}function We(e,t,n){let o=de(e);return o.length===0?"nochange":e==="copilot_cli"?ze(e,t,n,o):Ve(e,t,n,o)}function me(e,t,n=process.env){return Ge(n).map(o=>{try{let r=We(o,e,t);return {host:o,status:r,events:de(o)}}catch(r){return {host:o,status:"error",events:[],error:r.message}}})}var Xe=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTIONS","GITLAB_CI","CIRCLECI","TRAVIS","BUILDKITE","JENKINS_URL","TEAMCITY_VERSION","TF_BUILD","APPVEYOR","CODEBUILD_BUILD_ID","DRONE","NETLIFY","VERCEL"];function J(e){return e!==void 0&&e!==""&&e!=="0"&&e.toLowerCase()!=="false"}function qe(e){return J(e.OPENCRATER_DISABLE)||J(e.TSN_DISABLE)}function Ze(e){return Xe.some(t=>J(e[t]))}function v(e){return e?{...C,...e}:C}function ge(e,t={}){if(qe(e.env))return "env_disabled";if(e.state.optOut)return "opt_out";let n=v(e.state.cachedConfig);if(n.killSwitch)return "kill_switch";if(Ze(e.env))return "ci";if(!t.skipTTY&&false);if(!t.skipFrequency){let o=n.minIntervalSeconds*1e3;if(e.state.lastShownAt>0&&e.now-e.state.lastShownAt<o)return "frequency"}return null}var Qe=new Set(["the","and","for","but","not","you","all","any","can","this","that","with","have","will","your","from","they","what","when","where","how","why","make","fix","add","update","remove","create","delete","change","error","errors","bug","bugs","file","files","code","test","tests","run","running","build","please","help","want","need","should","would","could","into","about","then","here","there","now","new","use","using","used","work","working","works","check","show","see","look","get","set","let","lets","dont","cant","issue"]);function et(e){if(e.includes("/")||e.includes("\\")||e.includes("@")||e.includes("://"))return true;let t=e.toLowerCase();return !!(/^(sk|pk|rk|ock|ghp|gho|ghs|xox|akia|eyj|npm|glpat)[-_]/.test(t)||e.length>=16&&/^[0-9a-f]+$/i.test(e)||e.length>=20&&/^[A-Za-z0-9+/=_-]+$/.test(e)&&/[A-Z]/.test(e)&&/[0-9]/.test(e))}function tt(e,t=12){let n=[];for(let o of e.slice(0,2e3).split(/\s+/))if(!(!o||et(o)))for(let r of o.split(/[^A-Za-z0-9+#.]+|(?<=[a-z0-9])(?=[A-Z])/)){let i=r.replace(/^[.]+|[.]+$/g,"").toLowerCase();if(!(i.length<3||i.length>24)&&!(/^\d+$/.test(i)||Qe.has(i))&&!n.includes(i)&&(n.push(i),n.length>=t))return n}return n}function G(e){let t=[];typeof e.prompt=="string"&&t.push(e.prompt);let n=e.cwd;if(typeof n=="string"&&n.length>0){let o=n.replace(/[\\/]+$/,""),r=o.split(/[\\/]/).pop()??"",i=(process.env.HOME??process.env.USERPROFILE??"").replace(/[\\/]+$/,""),s=process.env.USER??process.env.USERNAME??"";o!==i&&r!==s&&r.length>0&&t.push(r.replace(/[-_]/g," "));}return tt(t.join(" "))}function K(e,t,n){let o=new Map;for(let{topic:r,at:i}of e)n-i<216e5&&o.set(r,i);for(let r of t)o.set(r,n);return [...o.entries()].map(([r,i])=>({topic:r,at:i})).sort((r,i)=>i.at-r.at).slice(0,24)}function he(e,t){return e.filter(({at:n})=>t-n<216e5).sort((n,o)=>o.at-n.at).slice(0,12).map(({topic:n})=>n)}var rt=process.platform==="win32"?8e3:3200,ot=150,ye=250,it=2800;function st(e){let t={host:"claude_code"};for(let n=0;n<e.length;n++){let o=e[n],r=e[n+1];switch(o){case "--placement":r!==void 0&&(t.placement=r,n++);break;case "--key":r!==void 0&&(t.key=r,n++);break;case "--package":r!==void 0&&(t.package=r,n++);break;case "--host":(r==="claude_code"||r==="codex"||r==="openclaw"||r==="gemini_cli"||r==="copilot_cli"||r==="generic")&&(t.host=r,n++);break;}}return t}function ct(e){return new Promise(t=>{if(process.stdin.isTTY){t("");return}let n="",o=false,r=()=>{o||(o=true,t(n));},i=setTimeout(r,e);i.unref?.(),process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{n+=s;}),process.stdin.on("end",()=>{clearTimeout(i),r();}),process.stdin.on("error",()=>{clearTimeout(i),r();});})}var at="\\\\.\\CONOUT$";function lt(e){return !e||e==="?"||e==="??"||e==="-"?null:e.startsWith("/")?e:`/dev/${e}`}function ut(e){let t=e.match(/^\s*(\d+)\s+(\S+)/);return t?{ppid:Number(t[1]),tty:t[2]}:null}function pt(e){if(!Number.isInteger(e)||e<=0)return null;let t=e>>8&4095,n=e&255|e>>12&1048320;return t>=136&&t<=143?`/dev/pts/${(t-136)*256+n}`:t===4?n<64?`/dev/tty${n}`:`/dev/ttyS${n-64}`:null}function ft(e){let t=e.lastIndexOf(")");if(t<0)return null;let n=e.slice(t+1).trim().split(/\s+/),o=Number(n[1]),r=Number(n[4]);return !Number.isInteger(o)||!Number.isInteger(r)?null:{ppid:o,ttyNr:r}}function dt(e){try{let t=ft(l__namespace.readFileSync(`/proc/${e}/stat`,"utf8"));if(t)return {ppid:t.ppid,ttyPath:pt(t.ttyNr)}}catch{}try{let t=child_process.spawnSync("ps",["-o","ppid=,tty=","-p",String(e)],{encoding:"utf8",timeout:1500}).stdout?.trim();if(!t)return null;let n=ut(t);return n?{ppid:n.ppid,ttyPath:lt(n.tty)}:null}catch{return null}}function mt(){if(process.platform==="win32")return {path:at,ownerPid:null};let e=process.pid;for(let t=0;t<12&&e>1;t++){let n=dt(e);if(!n)return null;if(n.ttyPath)return {path:n.ttyPath,ownerPid:e};e=n.ppid;}return null}function gt(e){return e==="win32"?{detached:false,stdio:"ignore",windowsHide:false}:{detached:true,stdio:"ignore",windowsHide:false}}async function V(e,t,n,o,r){try{let i=d__namespace.join(__dirname,"paint.js"),s=v(t.cachedConfig),g=Math.min(Math.max(s.displayDurationSeconds??25,3),120),a={...e,format:n?.format,mediaUrl:n?.mediaUrl,mediaPixelUrl:n?.mediaPixelUrl,audioUrl:n?.audioUrl,impressionId:o,campaignId:r,apiOrigin:N(),durationMs:g*1e3,disclosure:!t.disclosureShown},u={...process.env,OPENCRATER_PAINT:JSON.stringify(a)};if(!u.OPENCRATER_TTY){let c=mt();c&&(u.OPENCRATER_TTY=c.path,c.ownerPid!==null&&(u.OPENCRATER_HOST_PID=String(c.ownerPid)));}let p=child_process.spawn(process.execPath,[i],{...gt(process.platform),env:u});process.platform==="win32"?await new Promise(c=>{let h=!1,x=()=>{h||(h=!0,c());};p.on("exit",x),p.on("error",x),setTimeout(x,7500);}):p.unref();}catch{}return {...t,lastShownAt:Date.now(),disclosureShown:true}}function ht(e){if(process.platform!=="win32")return false;try{let t=d__namespace.join(E__namespace.homedir(),".config","opencrater","painter.lock"),n=JSON.parse(l__namespace.readFileSync(t,"utf8"));if(typeof n.startedAt!="number"||Date.now()-n.startedAt>e+1500)return !1;if(typeof n.pid=="number")try{process.kill(n.pid,0);}catch(o){if(o.code==="ESRCH")return !1}return !0}catch{return false}}var yt=8e3;function St(){let e=d__namespace.join(E__namespace.homedir(),".config","opencrater","render.lock");try{let t=l__namespace.statSync(e);if(Date.now()-t.mtimeMs<yt)return !1;l__namespace.unlinkSync(e);}catch{}try{return l__namespace.mkdirSync(d__namespace.join(E__namespace.homedir(),".config","opencrater"),{recursive:!0}),l__namespace.writeFileSync(e,String(process.pid),{flag:"wx"}),!0}catch{return false}}function bt(e,t,n,o){if(!t)return true;let r=e.allowedPlacements[`${t}:${n}`];return r?r.includes(o):t==="opencrater"?_[n].includes(o):true}var kt=1440*60*1e3;function wt(){try{let e=d__namespace.join(E__namespace.homedir(),".config","opencrater","runtime"),t=d__namespace.join(e,"node_modules","opencrater","dist","hook.js"),n=d__namespace.join(e,".last-update");if(l__namespace.existsSync(t)){try{if(Date.now()-l__namespace.statSync(n).mtimeMs<kt)return}catch{}try{l__namespace.writeFileSync(n,String(Date.now()));}catch{return}}else {let o=d__namespace.join(e,".installing");try{l__namespace.mkdirSync(e,{recursive:!0});let r=l__namespace.statSync(o);if(Date.now()-r.mtimeMs<600*1e3)return}catch{}l__namespace.writeFileSync(o,String(Date.now()));}be(e);}catch{}}function be(e){child_process.spawn("npm",["install","--prefix",e,"opencrater@latest","--silent","--no-audit","--no-fund"],process.platform==="win32"?{detached:false,stdio:"ignore",windowsHide:true,shell:true}:{detached:true,stdio:"ignore"}).unref();}function Et(e,t){if(!t)return false;let n=s=>s.split(/[-+]/)[0].split(".").map(g=>parseInt(g,10)||0),o=n(e),r=n(t),i=Math.max(o.length,r.length);for(let s=0;s<i;s++){let g=o[s]??0,a=r[s]??0;if(g!==a)return g<a}return false}function Rt(){try{let e=d__namespace.join(E__namespace.homedir(),".config","opencrater","runtime"),t=d__namespace.join(e,".last-update"),n=d__namespace.join(e,".force-update");try{if(Date.now()-l__namespace.statSync(n).mtimeMs<600*1e3)return}catch{}l__namespace.mkdirSync(e,{recursive:!0}),l__namespace.writeFileSync(n,String(Date.now()));try{l__namespace.rmSync(t,{force:!0});}catch{}be(e);}catch{}}function Ot(){try{let e=d__namespace.join(E__namespace.homedir(),".config","opencrater");l__namespace.mkdirSync(e,{recursive:!0}),l__namespace.writeFileSync(d__namespace.join(e,"activity.signal"),String(Date.now()));}catch{}}var Tt=1440*60*1e3;function It(){try{let e=d__namespace.join(E__namespace.homedir(),".config","opencrater"),t=d__namespace.join(e,".last-host-check");try{if(Date.now()-l__namespace.statSync(t).mtimeMs<Tt)return}catch{}l__namespace.mkdirSync(e,{recursive:!0});try{l__namespace.writeFileSync(t,String(Date.now()));}catch{return}let n=D();if(n.optOut||n.integrations.length===0)return;for(let o of n.integrations)try{me(o.key,o.package);}catch{}}catch{}}async function Ct(){let e=st(process.argv.slice(2));Ot(),wt(),It();let t=await ct(ot),n={};if(t)try{n=JSON.parse(t);let h=n.hook_event_name;!e.placement&&typeof h=="string"&&(e.placement=h);}catch{}let o=e.placement??"SessionStart",r=D(),i=ge({env:process.env,state:r,now:Date.now()},{skipTTY:true});if(i!==null){if(i==="frequency"){let h=G(n);h.length>0&&y({...r,sessionTopics:K(r.sessionTopics,h,Date.now())});}m("hook suppressed:",i);return}if(r={...r,sessionTopics:K(r.sessionTopics,G(n),Date.now())},!bt(r,e.package,e.host,o)){y(r),m("hook gated: placement",o,"not selected for",e.package);return}let s=v(r.cachedConfig),a={origin:N(),timeoutMs:Math.min(s.serveTimeoutMs,it),installId:r.installId,topics:he(r.sessionTopics,Date.now())},{ad:u,pool:p}=U(r,Date.now());for(;u&&(F(u.campaignId)||H(u.campaignId));)m("hook: pooled ad skipped \u2014 campaign inside a local cooldown"),{ad:u,pool:p}=U({pool:p},Date.now());if((u||e.key)&&ht((s.displayDurationSeconds??25)*1e3)){y(r),m("hook: a card is already on screen \u2014 not rendering another");return}if((u||e.key)&&!St()){y(r),m("hook: render slot already claimed by a concurrent fire");return}if(u){L(u.campaignId),r=await V(M(u),{...r,pool:p},u.creative,u.impressionId,u.campaignId),y(r),await Promise.race([$(u.impressionId,a),new Promise(h=>setTimeout(h,ye).unref?.())]);return}if(p.length!==r.pool.length&&(r={...r,pool:p}),!e.key||!e.package){y(r),m("hook: pool empty and no --key/--package; nothing to render");return}let c=await z({publisherKey:e.key,packageName:e.package,placement:o,host:e.host},a);if(!c){y(r);return}if(r={...r,cachedConfig:c.config,configFetchedAt:Date.now()},Et(T,c.config.minSdkVersion)&&(m(`SDK ${T} below floor ${c.config.minSdkVersion} \u2014 forcing runtime update`),Rt()),e.package&&c.allowedPlacements&&(r={...r,allowedPlacements:{...r.allowedPlacements,[`${e.package}:${e.host}`]:c.allowedPlacements}}),c.fill&&c.ad){if(F(c.ad.campaignId)||H(c.ad.campaignId)){m("hook: served ad suppressed \u2014 campaign inside a local cooldown"),y(r);return}L(c.ad.campaignId),r=await V(M(c.ad),r,c.ad.creative,c.ad.impressionId,c.ad.campaignId),y(r),await Promise.race([$(c.ad.impressionId,a),new Promise(h=>setTimeout(h,ye).unref?.())]);return}c.fallback&&(r=await V(X(c.fallback),r)),y(r);}if(typeof O<"u"&&typeof module<"u"&&O.main===module){let e=setTimeout(()=>process.exit(0),rt);Ct().catch(t=>m(`opencrater-hook v${T} error:`,t)).finally(()=>{clearTimeout(e),process.exit(0);});}
|
|
6
|
+
exports.decodeTtyNr=pt;exports.painterSpawnOptions=gt;exports.parseProcStat=ft;exports.parsePsLine=ut;exports.resolveTtyPath=mt;exports.ttyNameToDevPath=lt;
|