PHP code example of 1994 / ghostwriter-core

1. Go to this page and download the library: Download 1994/ghostwriter-core library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

1994 / ghostwriter-core example snippets


use NineteenNinetyFour\Ghostwriter\Core\Prompts\PromptLibrary;
use NineteenNinetyFour\Ghostwriter\Core\Prompts\Vocabulary;

$prompts = new PromptLibrary(
    Vocabulary::statamic(),                      // or ::craft(), ::filament(), or your own
    fn (string $name): ?string => is_file($path = resource_path("ghostwriter/prompts/{$name}.md"))
        ? file_get_contents($path)
        : null,                                  // a site's override, or null for core's
);

$instructions = strtr($prompts->get('planner'), [
    '{{ count }}' => '8',
    '{{ voice }}' => $voice,
    // ...the addon fills its own {{ name }} placeholders, as before
]);

$studio = new Studio($providers, $prompts, $logger, StudioOptions::statamic());
$ideas = $studio->suggestIdeas(new PlanContext($groups, $plan, $voice, $steer));
$ideas->value;          // SuggestedIdea[]
$ideas->usage->output;  // tokens, retries 

$layouts = new Layouts(LayoutOptions::craft(), new HtmlDialect, new CraftLinks(hyper: [$hyper], link: [$link]));

$schema = Schema::fromSpecs($reader->read($entryType));
$pattern = $layouts->patterns()->find($schema, PatternFinder::choose($entries, $type->where));
$built = $layouts->builder()->build($draft->data, $schema, $pattern, $type->defaults);
$house = $layouts->houseStyle()->apply($built->data, $schema, $pattern->house, $entryId, $title);

$studioLayout = Layout::fromSchema($schema, $pattern, $layouts->describer());   // for the Studio

use NineteenNinetyFour\Ghostwriter\Core\Images\PhotoContext;
use NineteenNinetyFour\Ghostwriter\Core\Images\PhotoFinder;
use NineteenNinetyFour\Ghostwriter\Core\Images\StockSearch;

$stock = new StockSearch($http, $credentials, openverse: fn () => $settings->openverse, logger: $logger);
$finder = new PhotoFinder($stock, $providers, $prompts, $logger);

$results = $finder->find(
    PhotoContext::make($title, $label, $blockText, $pageText, $summary, shape: 'landscape', style: $imageryGuide),
    $referenceBytes,              // the images already in that place; [] is fine
    $typedSearches ?: null,       // null: the model chooses the searches
);

$json = $results->toArray();      // photos (with alt, asset_title, picked, reason), terms, judged, none_fit...

// When the person chooses one:
$file = $stock->fetch($source, $id);                    // looked up again by ID; https only; at most 15 MB
$name = $file->photo->filenameBase().'.'.$file->extension;
$alt = $file->photo->alt();

$sessions = new SessionGuard($store, $lock, DomainOptions::filament(shared: config('ghostwriter.shared_conversations')));

$session = $sessions->send($id, $message, new Viewer(auth()->id()));    // Busy (409) while someone's request runs
$sessions->change($id, fn (Session $s) => $s->answer($reply, $draft, $in, $out));   // in the job
$finished = Progress::of($session, Record::saved($published), $options)->finished;  // E6

use NineteenNinetyFour\Ghostwriter\Core\Ai\Http\GuzzleHttpClients;
use NineteenNinetyFour\Ghostwriter\Core\Ai\Providers;
use NineteenNinetyFour\Ghostwriter\Core\Ai\TextRequest;

$providers = new Providers($credentials, new GuzzleHttpClients(), $settings, $logger);

$response = $providers->text()->text(new TextRequest(
    agent: 'writer',
    instructions: $prompts->get('writer'),
    prompt: $prompt,
    history: Message::list($session->history),
));

$image = $providers->image()?->image(new ImageRequest('A lighthouse at dusk', $references, Shape::Landscape));

$providers = $providers->withSleeper(new RecordingSleeper)->withRetryPolicy(new RetryPolicy(attempts: 1));

$fake = $providers->fake();   // every text and image call goes to the fake from now on

$fake->respond('writer', '<reply>Here it is.</reply><draft>title: A</draft>');
$fake->respond('photo-picker', '3, 1', '2');                     // handed out in order; the last repeats
$fake->respond('planner', fn (TextRequest $r) => '<ideas>…</ideas>');
$fake->failWith('brief-writer', new RateLimited('Busy.', 'anthropic', 429));
$fake->respondWithImage(Image::fromPath(__DIR__.'/fixtures/photo.jpg'));

// ...run the code under test...

$fake->assertSent('photo-picker', fn (TextRequest $r) => count($r->images) === 9);
$fake->assertNotSent('writer');
$fake->assertImageSent(fn (ImageRequest $r) => $r->shape === Shape::Landscape);
$fake->assertNoImageSent();
$fake->assertNothingSent();
$fake->prompted('writer')[0]->prompt;
$fake->imageRequests;

$fake->reset('writer');   // forget the writer's queued answers and requests
$fake->reset();           // forget every answer and request, text and image

$providers->fake(FakeProvider::withoutKeys());   // no text key, no image key

$providers->configured();     // false
$providers->text();           // throws NotConfigured, worded as for a real missing key
$providers->image();          // null
$providers->imageHandle();    // null
$providers->keyStatus();      // every key false

$providers->fake()->unconfigured(text: false);   // a text key, but no image key
$providers->fake()->unconfigured(false, false);  // both keys back