@relvehq/agent-ready 0.2.1 → 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/README.md +51 -25
- package/SETUP.md +24 -7
- package/dist/bin/agent-ready.js +105 -11
- package/dist/refine/remote.d.ts +57 -0
- package/dist/refine/remote.js +238 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-admin.php +189 -2
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-markdown-builder.php +22 -14
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-refiner.php +894 -0
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-settings.php +89 -3
- package/dist/wp/relve-agent-ready/includes/class-relve-ar-store.php +40 -0
- package/dist/wp/relve-agent-ready/readme.txt +37 -4
- package/dist/wp/relve-agent-ready/relve-agent-ready.php +16 -5
- package/dist/wp/relve-agent-ready/uninstall.php +15 -4
- package/package.json +1 -1
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Settings form (Settings API, sanitised by Relve_AR_Settings::sanitize), a
|
|
6
6
|
* status panel with this site's three test commands, and the refined-files
|
|
7
|
-
* upload / clear actions (
|
|
8
|
-
*
|
|
7
|
+
* upload / clear actions, the OpenAI key rows (masked, never echoed), the
|
|
8
|
+
* rewrite status and "Rewrite all now" (admin-post.php, each checking
|
|
9
|
+
* manage_options and its own nonce), and a notice while rewriting is paused.
|
|
10
|
+
* All output is escaped.
|
|
9
11
|
*
|
|
10
12
|
* @package Relve_Agent_Ready
|
|
11
13
|
*/
|
|
@@ -33,6 +35,8 @@ class Relve_AR_Admin {
|
|
|
33
35
|
add_action( 'admin_init', array( __CLASS__, 'register' ) );
|
|
34
36
|
add_action( 'admin_post_relve_ar_upload', array( __CLASS__, 'handle_upload' ) );
|
|
35
37
|
add_action( 'admin_post_relve_ar_clear', array( __CLASS__, 'handle_clear' ) );
|
|
38
|
+
add_action( 'admin_post_relve_ar_refine_all', array( __CLASS__, 'handle_refine_all' ) );
|
|
39
|
+
add_action( 'admin_notices', array( __CLASS__, 'pause_notice' ) );
|
|
36
40
|
add_filter( 'plugin_action_links_' . plugin_basename( RELVE_AR_FILE ), array( __CLASS__, 'action_links' ) );
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -138,6 +142,7 @@ class Relve_AR_Admin {
|
|
|
138
142
|
check_admin_referer( 'relve_ar_clear' );
|
|
139
143
|
$store = new Relve_AR_Store();
|
|
140
144
|
$store->clear();
|
|
145
|
+
Relve_AR_Refiner::forget_all_meta();
|
|
141
146
|
self::redirect_with(
|
|
142
147
|
array(
|
|
143
148
|
'type' => 'success',
|
|
@@ -147,6 +152,63 @@ class Relve_AR_Admin {
|
|
|
147
152
|
);
|
|
148
153
|
}
|
|
149
154
|
|
|
155
|
+
/**
|
|
156
|
+
* "Rewrite all now": queue every published post; WP-Cron does the work.
|
|
157
|
+
*
|
|
158
|
+
* @return void
|
|
159
|
+
*/
|
|
160
|
+
public static function handle_refine_all() {
|
|
161
|
+
if ( ! current_user_can( 'manage_options' ) ) {
|
|
162
|
+
wp_die( esc_html__( 'You are not allowed to do this.', 'relve-agent-ready' ), 403 );
|
|
163
|
+
}
|
|
164
|
+
check_admin_referer( 'relve_ar_refine_all' );
|
|
165
|
+
$s = Relve_AR_Settings::get();
|
|
166
|
+
if ( '' === $s['openai_key'] ) {
|
|
167
|
+
self::redirect_with(
|
|
168
|
+
array(
|
|
169
|
+
'type' => 'error',
|
|
170
|
+
'message' => __( 'Save an OpenAI key first.', 'relve-agent-ready' ),
|
|
171
|
+
'reasons' => array(),
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
$n = Relve_AR_Refiner::start_all();
|
|
176
|
+
self::redirect_with(
|
|
177
|
+
array(
|
|
178
|
+
'type' => $n ? 'success' : 'error',
|
|
179
|
+
/* translators: %d: number of posts. */
|
|
180
|
+
'message' => $n ? sprintf( _n( 'Rewriting %d post in the background, 5 at a time. Reload this page to see progress.', 'Rewriting %d posts in the background, 5 at a time. Reload this page to see progress.', $n, 'relve-agent-ready' ), $n ) : __( 'No published posts of the enabled types were found.', 'relve-agent-ready' ),
|
|
181
|
+
'reasons' => array(),
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Admin notice while rewriting is paused on a key problem.
|
|
188
|
+
*
|
|
189
|
+
* @return void
|
|
190
|
+
*/
|
|
191
|
+
public static function pause_notice() {
|
|
192
|
+
if ( ! current_user_can( 'manage_options' ) ) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
$state = Relve_AR_Refiner::state();
|
|
196
|
+
if ( '' === $state['paused'] ) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
$url = admin_url( 'options-general.php?page=' . self::PAGE );
|
|
200
|
+
?>
|
|
201
|
+
<div class="notice notice-error">
|
|
202
|
+
<p>
|
|
203
|
+
<strong><?php esc_html_e( 'Agent Ready paused rewriting posts.', 'relve-agent-ready' ); ?></strong>
|
|
204
|
+
<?php echo esc_html( Relve_AR_Refiner::error_label( $state['paused'] ) ); ?>
|
|
205
|
+
<code><?php echo esc_html( $state['paused'] ); ?></code>
|
|
206
|
+
<a href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'Open Agent Ready settings', 'relve-agent-ready' ); ?></a>
|
|
207
|
+
</p>
|
|
208
|
+
</div>
|
|
209
|
+
<?php
|
|
210
|
+
}
|
|
211
|
+
|
|
150
212
|
/**
|
|
151
213
|
* Keep a notice for this user and go back to the settings page.
|
|
152
214
|
*
|
|
@@ -255,10 +317,21 @@ class Relve_AR_Admin {
|
|
|
255
317
|
<?php endforeach; ?>
|
|
256
318
|
</td>
|
|
257
319
|
</tr>
|
|
320
|
+
<?php self::render_refine_fields( $s ); ?>
|
|
258
321
|
</table>
|
|
259
322
|
<?php submit_button(); ?>
|
|
260
323
|
</form>
|
|
261
324
|
|
|
325
|
+
<h2><?php esc_html_e( 'Better Markdown with your own OpenAI key', 'relve-agent-ready' ); ?></h2>
|
|
326
|
+
<p><?php esc_html_e( 'Each published post is sent to Relve\'s refine service, which rewrites it with Relve\'s prompt using your OpenAI key and returns clean Markdown. The result is stored as that post\'s refined file and served first. Your key passes through Relve\'s server for that single call only; it is not stored or logged there. You pay OpenAI for the tokens.', 'relve-agent-ready' ); ?></p>
|
|
327
|
+
<?php self::render_refine_status( $s, Relve_AR_Refiner::state(), Relve_AR_Refiner::queue(), Relve_AR_Refiner::count_rewritten() ); ?>
|
|
328
|
+
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
|
329
|
+
<input type="hidden" name="action" value="relve_ar_refine_all" />
|
|
330
|
+
<?php wp_nonce_field( 'relve_ar_refine_all' ); ?>
|
|
331
|
+
<?php submit_button( __( 'Rewrite all now', 'relve-agent-ready' ), 'secondary', 'submit', false, '' === $s['openai_key'] ? array( 'disabled' => 'disabled' ) : array() ); ?>
|
|
332
|
+
<p class="description"><?php esc_html_e( 'Queues every published post of the enabled types; WP-Cron rewrites 5 per run. Pages that have not changed since their last rewrite cost nothing. To start again from scratch, use "Clear refined files" below.', 'relve-agent-ready' ); ?></p>
|
|
333
|
+
</form>
|
|
334
|
+
|
|
262
335
|
<h2><?php esc_html_e( 'Refined files from Relve', 'relve-agent-ready' ); ?></h2>
|
|
263
336
|
<p>
|
|
264
337
|
<?php
|
|
@@ -285,6 +358,120 @@ class Relve_AR_Admin {
|
|
|
285
358
|
<?php
|
|
286
359
|
}
|
|
287
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Settings rows: OpenAI key (masked, never echoed), model, rewrite on save.
|
|
363
|
+
*
|
|
364
|
+
* @param array $s Settings.
|
|
365
|
+
* @return void
|
|
366
|
+
*/
|
|
367
|
+
public static function render_refine_fields( $s ) {
|
|
368
|
+
$opt = Relve_AR_Settings::OPTION;
|
|
369
|
+
$masked = Relve_AR_Settings::mask_key( $s['openai_key'] );
|
|
370
|
+
?>
|
|
371
|
+
<tr>
|
|
372
|
+
<th scope="row"><label for="relve-ar-openai-key"><?php esc_html_e( 'OpenAI key', 'relve-agent-ready' ); ?></label></th>
|
|
373
|
+
<td>
|
|
374
|
+
<?php if ( '' !== $masked ) : ?>
|
|
375
|
+
<p><?php esc_html_e( 'Saved key:', 'relve-agent-ready' ); ?> <code><?php echo esc_html( $masked ); ?></code></p>
|
|
376
|
+
<label>
|
|
377
|
+
<input type="checkbox" name="<?php echo esc_attr( $opt ); ?>[openai_key_remove]" value="1" />
|
|
378
|
+
<?php esc_html_e( 'Remove the saved key', 'relve-agent-ready' ); ?>
|
|
379
|
+
</label>
|
|
380
|
+
<?php endif; ?>
|
|
381
|
+
<p>
|
|
382
|
+
<input type="password" id="relve-ar-openai-key" class="regular-text code" name="<?php echo esc_attr( $opt ); ?>[openai_key_new]" value="" autocomplete="new-password" spellcheck="false" placeholder="<?php echo esc_attr( '' !== $masked ? __( 'Replace key', 'relve-agent-ready' ) : 'sk-...' ); ?>" />
|
|
383
|
+
</p>
|
|
384
|
+
<p class="description"><?php esc_html_e( 'Stored in this site\'s own database. Sent only to Relve\'s refine endpoint over https, for one call at a time; Relve does not store or log it. Leave empty to keep the saved key.', 'relve-agent-ready' ); ?></p>
|
|
385
|
+
</td>
|
|
386
|
+
</tr>
|
|
387
|
+
<tr>
|
|
388
|
+
<th scope="row"><label for="relve-ar-model"><?php esc_html_e( 'Model', 'relve-agent-ready' ); ?></label></th>
|
|
389
|
+
<td>
|
|
390
|
+
<select id="relve-ar-model" name="<?php echo esc_attr( $opt ); ?>[refine_model]">
|
|
391
|
+
<?php foreach ( Relve_AR_Settings::MODELS as $model ) : ?>
|
|
392
|
+
<option value="<?php echo esc_attr( $model ); ?>" <?php selected( $s['refine_model'], $model ); ?>><?php echo esc_html( $model ); ?></option>
|
|
393
|
+
<?php endforeach; ?>
|
|
394
|
+
</select>
|
|
395
|
+
</td>
|
|
396
|
+
</tr>
|
|
397
|
+
<tr>
|
|
398
|
+
<th scope="row"><?php esc_html_e( 'Rewrite on publish', 'relve-agent-ready' ); ?></th>
|
|
399
|
+
<td>
|
|
400
|
+
<label>
|
|
401
|
+
<input type="checkbox" name="<?php echo esc_attr( $opt ); ?>[refine_on_save]" value="1" <?php checked( $s['refine_on_save'] ); ?> />
|
|
402
|
+
<?php esc_html_e( 'Rewrite a post in the background (WP-Cron, about 30 seconds later) when it is published or updated. Needs a saved key and "Enabled".', 'relve-agent-ready' ); ?>
|
|
403
|
+
</label>
|
|
404
|
+
</td>
|
|
405
|
+
</tr>
|
|
406
|
+
<?php
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Rewrite status: key, posts rewritten, last run, last error, progress.
|
|
411
|
+
*
|
|
412
|
+
* @param array $s Settings.
|
|
413
|
+
* @param array $state Refiner state.
|
|
414
|
+
* @param array $q Refiner queue.
|
|
415
|
+
* @param int $rewritten Posts with a rewritten file.
|
|
416
|
+
* @return void
|
|
417
|
+
*/
|
|
418
|
+
public static function render_refine_status( $s, $state, $q, $rewritten ) {
|
|
419
|
+
$format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
|
|
420
|
+
?>
|
|
421
|
+
<table class="widefat striped" style="max-width:60em">
|
|
422
|
+
<tbody>
|
|
423
|
+
<tr>
|
|
424
|
+
<td><?php esc_html_e( 'OpenAI key saved', 'relve-agent-ready' ); ?></td>
|
|
425
|
+
<td><strong><?php echo '' !== $s['openai_key'] ? esc_html__( 'Yes', 'relve-agent-ready' ) : esc_html__( 'No', 'relve-agent-ready' ); ?></strong></td>
|
|
426
|
+
</tr>
|
|
427
|
+
<tr>
|
|
428
|
+
<td><?php esc_html_e( 'Posts rewritten', 'relve-agent-ready' ); ?></td>
|
|
429
|
+
<td><?php echo esc_html( (string) (int) $rewritten ); ?></td>
|
|
430
|
+
</tr>
|
|
431
|
+
<tr>
|
|
432
|
+
<td><?php esc_html_e( 'Last run', 'relve-agent-ready' ); ?></td>
|
|
433
|
+
<td><?php echo $state['last_run'] ? esc_html( wp_date( $format, (int) $state['last_run'] ) ) : esc_html__( 'Never', 'relve-agent-ready' ); ?></td>
|
|
434
|
+
</tr>
|
|
435
|
+
<tr>
|
|
436
|
+
<td><?php esc_html_e( 'Last error', 'relve-agent-ready' ); ?></td>
|
|
437
|
+
<td>
|
|
438
|
+
<?php if ( '' === $state['last_error'] ) : ?>
|
|
439
|
+
<?php esc_html_e( 'None', 'relve-agent-ready' ); ?>
|
|
440
|
+
<?php else : ?>
|
|
441
|
+
<code><?php echo esc_html( $state['last_error'] ); ?></code>
|
|
442
|
+
<?php echo esc_html( Relve_AR_Refiner::error_label( $state['last_error'] ) ); ?>
|
|
443
|
+
<?php if ( $state['last_error_at'] ) : ?>
|
|
444
|
+
(<?php echo esc_html( wp_date( $format, (int) $state['last_error_at'] ) ); ?><?php echo $state['last_error_post'] ? esc_html( ', post #' . (int) $state['last_error_post'] ) : ''; ?>)
|
|
445
|
+
<?php endif; ?>
|
|
446
|
+
<?php endif; ?>
|
|
447
|
+
</td>
|
|
448
|
+
</tr>
|
|
449
|
+
<tr>
|
|
450
|
+
<td><?php esc_html_e( 'Rewrite all', 'relve-agent-ready' ); ?></td>
|
|
451
|
+
<td>
|
|
452
|
+
<?php
|
|
453
|
+
if ( $q['ids'] ) {
|
|
454
|
+
/* translators: 1: posts done, 2: posts queued. */
|
|
455
|
+
echo esc_html( sprintf( __( 'In progress: %1$d / %2$d', 'relve-agent-ready' ), $q['done'], $q['total'] ) );
|
|
456
|
+
if ( '' !== $state['paused'] ) {
|
|
457
|
+
echo ' ';
|
|
458
|
+
/* translators: %s: error code. */
|
|
459
|
+
echo esc_html( sprintf( __( '(paused: %s; fix the key and it resumes)', 'relve-agent-ready' ), $state['paused'] ) );
|
|
460
|
+
}
|
|
461
|
+
} elseif ( is_array( $state['last_batch'] ) && isset( $state['last_batch']['done'], $state['last_batch']['total'] ) ) {
|
|
462
|
+
/* translators: 1: posts done, 2: posts queued. */
|
|
463
|
+
echo esc_html( sprintf( __( 'Finished: %1$d / %2$d', 'relve-agent-ready' ), (int) $state['last_batch']['done'], (int) $state['last_batch']['total'] ) );
|
|
464
|
+
} else {
|
|
465
|
+
esc_html_e( 'Not run yet', 'relve-agent-ready' );
|
|
466
|
+
}
|
|
467
|
+
?>
|
|
468
|
+
</td>
|
|
469
|
+
</tr>
|
|
470
|
+
</tbody>
|
|
471
|
+
</table>
|
|
472
|
+
<?php
|
|
473
|
+
}
|
|
474
|
+
|
|
288
475
|
/**
|
|
289
476
|
* Status panel.
|
|
290
477
|
*
|
|
@@ -271,20 +271,8 @@ class Relve_AR_Markdown_Builder {
|
|
|
271
271
|
* @return string
|
|
272
272
|
*/
|
|
273
273
|
public static function for_post( $post, $canonical ) {
|
|
274
|
-
$title
|
|
275
|
-
|
|
276
|
-
// Render the content the way the theme would (blocks, shortcodes,
|
|
277
|
-
// embeds), with the post set up as the global post.
|
|
278
|
-
$previous_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
|
|
279
|
-
$GLOBALS['post'] = $post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
|
280
|
-
setup_postdata( $post );
|
|
281
|
-
$html = apply_filters( 'the_content', $post->post_content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- core hook.
|
|
282
|
-
$html = str_replace( ']]>', ']]>', (string) $html );
|
|
283
|
-
$GLOBALS['post'] = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
|
284
|
-
if ( $previous_post instanceof WP_Post ) {
|
|
285
|
-
setup_postdata( $previous_post );
|
|
286
|
-
}
|
|
287
|
-
|
|
274
|
+
$title = html_entity_decode( wp_strip_all_tags( get_the_title( $post ) ), ENT_QUOTES, 'UTF-8' );
|
|
275
|
+
$html = self::render_content( $post );
|
|
288
276
|
$content = Relve_AR_Converter::convert( $html, $canonical, array( 'demote_h1' => true ) );
|
|
289
277
|
|
|
290
278
|
$image_url = null;
|
|
@@ -332,6 +320,26 @@ class Relve_AR_Markdown_Builder {
|
|
|
332
320
|
return self::assemble( $fields, apply_filters( 'relve_agent_ready_markdown_body', $body, $post ) );
|
|
333
321
|
}
|
|
334
322
|
|
|
323
|
+
/**
|
|
324
|
+
* The post's content rendered the way the theme would (blocks, shortcodes,
|
|
325
|
+
* embeds), with the post set up as the global post.
|
|
326
|
+
*
|
|
327
|
+
* @param WP_Post $post Post.
|
|
328
|
+
* @return string HTML.
|
|
329
|
+
*/
|
|
330
|
+
public static function render_content( $post ) {
|
|
331
|
+
$previous_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
|
|
332
|
+
$GLOBALS['post'] = $post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
|
333
|
+
setup_postdata( $post );
|
|
334
|
+
$html = apply_filters( 'the_content', $post->post_content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- core hook.
|
|
335
|
+
$html = str_replace( ']]>', ']]>', (string) $html );
|
|
336
|
+
$GLOBALS['post'] = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
|
337
|
+
if ( $previous_post instanceof WP_Post ) {
|
|
338
|
+
setup_postdata( $previous_post );
|
|
339
|
+
}
|
|
340
|
+
return $html;
|
|
341
|
+
}
|
|
342
|
+
|
|
335
343
|
/**
|
|
336
344
|
* Front matter for a stored (refined) file that has none of its own.
|
|
337
345
|
*
|