@relvehq/agent-ready 0.0.0-stage → 0.3.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 +21 -0
- package/README.md +364 -3
- package/SETUP.md +354 -0
- package/dist/bin/agent-ready.d.ts +23 -0
- package/dist/bin/agent-ready.js +444 -0
- package/dist/cli/init.d.ts +70 -0
- package/dist/cli/init.js +366 -0
- package/dist/core/accept.d.ts +8 -0
- package/dist/core/accept.js +76 -0
- package/dist/core/config.d.ts +145 -0
- package/dist/core/config.js +103 -0
- package/dist/core/convert.d.ts +22 -0
- package/dist/core/convert.js +334 -0
- package/dist/core/detect.d.ts +30 -0
- package/dist/core/detect.js +82 -0
- package/dist/core/easy.d.ts +19 -0
- package/dist/core/easy.js +117 -0
- package/dist/core/enrich.d.ts +30 -0
- package/dist/core/enrich.js +155 -0
- package/dist/core/llms.d.ts +11 -0
- package/dist/core/llms.js +71 -0
- package/dist/core/report.d.ts +15 -0
- package/dist/core/report.js +46 -0
- package/dist/core/resolve.d.ts +43 -0
- package/dist/core/resolve.js +204 -0
- package/dist/core/respond.d.ts +18 -0
- package/dist/core/respond.js +59 -0
- package/dist/core/sitemap.d.ts +31 -0
- package/dist/core/sitemap.js +140 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +76 -0
- package/dist/next/dashboard.d.ts +14 -0
- package/dist/next/dashboard.js +56 -0
- package/dist/next/index.d.ts +42 -0
- package/dist/next/index.js +100 -0
- package/dist/next/route.d.ts +26 -0
- package/dist/next/route.js +167 -0
- package/dist/node/index.d.ts +8 -0
- package/dist/node/index.js +191 -0
- package/dist/proof/audit.d.ts +47 -0
- package/dist/proof/audit.js +253 -0
- package/dist/proof/bots.d.ts +24 -0
- package/dist/proof/bots.js +60 -0
- package/dist/proof/dashboard.d.ts +8 -0
- package/dist/proof/dashboard.js +77 -0
- package/dist/proof/hits.d.ts +18 -0
- package/dist/proof/hits.js +51 -0
- package/dist/proof/jsonl.d.ts +5 -0
- package/dist/proof/jsonl.js +80 -0
- package/dist/proof/stats.d.ts +39 -0
- package/dist/proof/stats.js +127 -0
- package/dist/refine/check.d.ts +17 -0
- package/dist/refine/check.js +134 -0
- package/dist/refine/extract.d.ts +7 -0
- package/dist/refine/extract.js +120 -0
- package/dist/refine/file-store.d.ts +6 -0
- package/dist/refine/file-store.js +87 -0
- package/dist/refine/model.d.ts +30 -0
- package/dist/refine/model.js +105 -0
- package/dist/refine/prompts.d.ts +49 -0
- package/dist/refine/prompts.js +178 -0
- package/dist/refine/refine.d.ts +38 -0
- package/dist/refine/refine.js +75 -0
- package/dist/refine/remote.d.ts +57 -0
- package/dist/refine/remote.js +238 -0
- package/dist/refine/run.d.ts +52 -0
- package/dist/refine/run.js +66 -0
- package/dist/refine/types.d.ts +17 -0
- package/dist/refine/types.js +8 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-admin.php +550 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-converter.php +762 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-llms.php +192 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-markdown-builder.php +455 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-negotiation.php +334 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-refiner.php +894 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-response.php +226 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-router.php +421 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-settings.php +201 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-store.php +583 -0
- package/dist/wp/relve-agent-ready/includes/index.php +2 -0
- package/dist/wp/relve-agent-ready/index.php +2 -0
- package/dist/wp/relve-agent-ready/readme.txt +108 -0
- package/dist/wp/relve-agent-ready/relve-agent-ready.php +81 -0
- package/dist/wp/relve-agent-ready/uninstall.php +35 -0
- package/package.json +64 -6
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* Settings: one option array, `relve_agent_ready`.
|
|
4
|
+
*
|
|
5
|
+
* enabled bool default false (installing changes nothing)
|
|
6
|
+
* post_types string[] default post, page
|
|
7
|
+
* excluded_paths string one path prefix per line
|
|
8
|
+
* llms_mode string auto|on|off, default auto
|
|
9
|
+
* openai_key string the site's own OpenAI key (stored here only, never
|
|
10
|
+
* shown in full; sent only to the Relve refine endpoint)
|
|
11
|
+
* refine_model string gpt-4o-mini (default), gpt-4o, gpt-4.1, gpt-4.1-mini
|
|
12
|
+
* refine_on_save bool default true (only acts once a key is saved)
|
|
13
|
+
*
|
|
14
|
+
* The settings form never posts `openai_key`; it posts `openai_key_new` (a
|
|
15
|
+
* replacement, empty = keep) and `openai_key_remove`. A submission without
|
|
16
|
+
* either keeps the saved key.
|
|
17
|
+
*
|
|
18
|
+
* @package Relve_Agent_Ready
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
22
|
+
exit;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Settings access and sanitising.
|
|
27
|
+
*/
|
|
28
|
+
class Relve_AR_Settings {
|
|
29
|
+
|
|
30
|
+
const OPTION = 'relve_agent_ready';
|
|
31
|
+
|
|
32
|
+
/** Paths never worth serving as Markdown (segment-aware prefixes). */
|
|
33
|
+
const DEFAULT_EXCLUDED = "/wp-admin\n/wp-login.php\n/wp-json\n/wp-content\n/wp-includes\n/feed\n/cart\n/checkout\n/my-account\n/account";
|
|
34
|
+
|
|
35
|
+
/** Models the Relve refine endpoint accepts (contract.md). */
|
|
36
|
+
const MODELS = array( 'gpt-4o-mini', 'gpt-4o', 'gpt-4.1', 'gpt-4.1-mini' );
|
|
37
|
+
|
|
38
|
+
/** Default model: fast enough for the endpoint's ~30 s request limit. */
|
|
39
|
+
const DEFAULT_MODEL = 'gpt-4o-mini';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Defaults.
|
|
43
|
+
*
|
|
44
|
+
* @return array
|
|
45
|
+
*/
|
|
46
|
+
public static function defaults() {
|
|
47
|
+
return array(
|
|
48
|
+
'enabled' => false,
|
|
49
|
+
'post_types' => array( 'post', 'page' ),
|
|
50
|
+
'excluded_paths' => self::DEFAULT_EXCLUDED,
|
|
51
|
+
'llms_mode' => 'auto',
|
|
52
|
+
'openai_key' => '',
|
|
53
|
+
'refine_model' => self::DEFAULT_MODEL,
|
|
54
|
+
'refine_on_save' => true,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Masked key for display: "sk-...abcd". Never the full key.
|
|
60
|
+
*
|
|
61
|
+
* @param string $key Key.
|
|
62
|
+
* @return string
|
|
63
|
+
*/
|
|
64
|
+
public static function mask_key( $key ) {
|
|
65
|
+
$key = (string) $key;
|
|
66
|
+
if ( '' === $key ) {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
if ( strlen( $key ) < 12 ) {
|
|
70
|
+
return '****';
|
|
71
|
+
}
|
|
72
|
+
return substr( $key, 0, 3 ) . '...' . substr( $key, -4 );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A cleaned key, or null when it does not look like an OpenAI key.
|
|
77
|
+
*
|
|
78
|
+
* @param string $raw Raw input.
|
|
79
|
+
* @return string|null
|
|
80
|
+
*/
|
|
81
|
+
public static function clean_key( $raw ) {
|
|
82
|
+
$key = preg_replace( '/\s+/', '', (string) $raw );
|
|
83
|
+
if ( null === $key || ! preg_match( '/^[A-Za-z0-9_\-]{20,300}$/', $key ) ) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return $key;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Current settings merged over the defaults, plus "excluded" as a list.
|
|
91
|
+
*
|
|
92
|
+
* @return array
|
|
93
|
+
*/
|
|
94
|
+
public static function get() {
|
|
95
|
+
$stored = get_option( self::OPTION, array() );
|
|
96
|
+
$s = array_merge( self::defaults(), is_array( $stored ) ? $stored : array() );
|
|
97
|
+
$s['enabled'] = (bool) $s['enabled'];
|
|
98
|
+
$s['post_types'] = array_values( array_filter( (array) $s['post_types'], 'is_string' ) );
|
|
99
|
+
$s['excluded'] = self::lines( $s['excluded_paths'] );
|
|
100
|
+
$s['openai_key'] = is_string( $s['openai_key'] ) ? $s['openai_key'] : '';
|
|
101
|
+
$s['refine_model'] = in_array( $s['refine_model'], self::MODELS, true ) ? $s['refine_model'] : self::DEFAULT_MODEL;
|
|
102
|
+
$s['refine_on_save'] = (bool) $s['refine_on_save'];
|
|
103
|
+
return $s;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Split the excluded-paths text into prefixes.
|
|
108
|
+
*
|
|
109
|
+
* @param string $text Text.
|
|
110
|
+
* @return string[]
|
|
111
|
+
*/
|
|
112
|
+
public static function lines( $text ) {
|
|
113
|
+
$out = array();
|
|
114
|
+
foreach ( preg_split( '/\r\n|\r|\n/', (string) $text ) as $line ) {
|
|
115
|
+
$line = trim( $line );
|
|
116
|
+
if ( '' !== $line ) {
|
|
117
|
+
$out[] = $line;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return $out;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sanitise a submitted settings array (register_setting callback).
|
|
125
|
+
*
|
|
126
|
+
* @param mixed $input Raw input.
|
|
127
|
+
* @return array
|
|
128
|
+
*/
|
|
129
|
+
public static function sanitize( $input ) {
|
|
130
|
+
$input = is_array( $input ) ? $input : array();
|
|
131
|
+
$out = self::defaults();
|
|
132
|
+
|
|
133
|
+
$out['enabled'] = ! empty( $input['enabled'] );
|
|
134
|
+
|
|
135
|
+
$public = function_exists( 'get_post_types' ) ? get_post_types( array( 'public' => true ) ) : array( 'post' => 'post', 'page' => 'page' );
|
|
136
|
+
$types = array();
|
|
137
|
+
foreach ( (array) ( isset( $input['post_types'] ) ? $input['post_types'] : array() ) as $t ) {
|
|
138
|
+
$t = sanitize_key( (string) $t );
|
|
139
|
+
if ( 'attachment' !== $t && isset( $public[ $t ] ) ) {
|
|
140
|
+
$types[] = $t;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
$out['post_types'] = array_values( array_unique( $types ) );
|
|
144
|
+
|
|
145
|
+
$paths = array();
|
|
146
|
+
foreach ( self::lines( isset( $input['excluded_paths'] ) ? (string) $input['excluded_paths'] : '' ) as $line ) {
|
|
147
|
+
$line = sanitize_text_field( $line );
|
|
148
|
+
$line = preg_replace( '#[^A-Za-z0-9/_.~%@!$&\'()*+,;=:-]#', '', $line );
|
|
149
|
+
if ( '' === $line ) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if ( '/' !== $line[0] ) {
|
|
153
|
+
$line = '/' . $line;
|
|
154
|
+
}
|
|
155
|
+
$paths[] = $line;
|
|
156
|
+
if ( count( $paths ) >= 200 ) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
$out['excluded_paths'] = implode( "\n", array_unique( $paths ) );
|
|
161
|
+
|
|
162
|
+
$mode = isset( $input['llms_mode'] ) ? (string) $input['llms_mode'] : 'auto';
|
|
163
|
+
$out['llms_mode'] = in_array( $mode, array( 'auto', 'on', 'off' ), true ) ? $mode : 'auto';
|
|
164
|
+
|
|
165
|
+
// OpenAI key: replace, remove, or keep. WordPress may run this callback
|
|
166
|
+
// a second time on its own output (first save), which carries
|
|
167
|
+
// `openai_key` itself; that value is re-validated and kept.
|
|
168
|
+
$stored = get_option( self::OPTION, array() );
|
|
169
|
+
$current = ( is_array( $stored ) && isset( $stored['openai_key'] ) && is_string( $stored['openai_key'] ) ) ? $stored['openai_key'] : '';
|
|
170
|
+
$new = isset( $input['openai_key_new'] ) ? trim( (string) $input['openai_key_new'] ) : '';
|
|
171
|
+
$changed = false;
|
|
172
|
+
if ( '' !== $new ) {
|
|
173
|
+
$clean = self::clean_key( $new );
|
|
174
|
+
if ( null === $clean ) {
|
|
175
|
+
$out['openai_key'] = $current;
|
|
176
|
+
if ( function_exists( 'add_settings_error' ) ) {
|
|
177
|
+
add_settings_error( self::OPTION, 'relve_ar_bad_key', __( 'That does not look like an OpenAI API key. The saved key was kept.', 'relve-agent-ready' ) );
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
$out['openai_key'] = $clean;
|
|
181
|
+
$changed = $clean !== $current;
|
|
182
|
+
}
|
|
183
|
+
} elseif ( ! empty( $input['openai_key_remove'] ) ) {
|
|
184
|
+
$out['openai_key'] = '';
|
|
185
|
+
$changed = '' !== $current;
|
|
186
|
+
} elseif ( isset( $input['openai_key'] ) ) {
|
|
187
|
+
$clean = self::clean_key( (string) $input['openai_key'] );
|
|
188
|
+
$out['openai_key'] = null === $clean ? $current : $clean;
|
|
189
|
+
} else {
|
|
190
|
+
$out['openai_key'] = $current;
|
|
191
|
+
}
|
|
192
|
+
if ( $changed && class_exists( 'Relve_AR_Refiner' ) ) {
|
|
193
|
+
Relve_AR_Refiner::key_changed( '' !== $out['openai_key'] );
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
$model = isset( $input['refine_model'] ) ? (string) $input['refine_model'] : self::DEFAULT_MODEL;
|
|
197
|
+
$out['refine_model'] = in_array( $model, self::MODELS, true ) ? $model : self::DEFAULT_MODEL;
|
|
198
|
+
$out['refine_on_save'] = ! empty( $input['refine_on_save'] );
|
|
199
|
+
return $out;
|
|
200
|
+
}
|
|
201
|
+
}
|