Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { mcpAnalyticsCommand } from './src/commands/mcp-analytics';
import { replayVisionCommand } from './src/commands/replay-vision';
import { aiObservabilityCommand } from './src/commands/ai-observability';
import { metricsCommand } from './src/commands/metrics';
import { shakespeareCommand } from './src/commands/shakespeare';
import { auditCommand } from './src/commands/audit';
import { doctorCommand } from './src/commands/doctor';
import { migrateCommand } from './src/commands/migrate';
Expand Down Expand Up @@ -91,6 +92,7 @@ Wizard.use(basicIntegrationCommand)
.use(replayVisionCommand)
.use(aiObservabilityCommand)
.use(metricsCommand)
.use(shakespeareCommand)
.use(cliCommand)
.use(auditCommand)
.use(doctorCommand)
Expand Down
11 changes: 11 additions & 0 deletions src/commands/shakespeare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { shakespeareConfig } from '@lib/programs/shakespeare/index';

import type { Command } from './command';
import { nativeCommandFactory } from './factories/native-command-factory';

/**
* `wizard shakespeare` — internal test-only command. See
* `src/lib/programs/shakespeare/index.ts` for why this exists.
*/
export const shakespeareCommand: Command =
nativeCommandFactory(shakespeareConfig);
3 changes: 3 additions & 0 deletions src/lib/agent/runner/switchboard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ export const PROGRAM_BINDINGS: Partial<Record<ProgramId, ProgramBinding>> = {
model: SONNET_5_MODEL,
},
slack: DEFAULT_BINDING,
// Fixed skillId, single variant — no self-selection reasoning needed, so
// the plain default binding (unlike ai-observability).
shakespeare: DEFAULT_BINDING,
};

// ── Unified resolver ────────────────────────────────────────────────────
Expand Down
3 changes: 3 additions & 0 deletions src/lib/programs/program-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { replayVisionConfig } from './replay-vision/index.js';
import { aiObservabilityConfig } from './ai-observability/index.js';
import { metricsConfig } from './metrics/index.js';
import { slackConnectConfig } from './slack/index.js';
import { shakespeareConfig } from './shakespeare/index.js';

// Generic skill program — runs an arbitrary context-mill skill chosen at
// dispatch time (session.skillId) rather than a registered named program.
Expand Down Expand Up @@ -85,6 +86,7 @@ export const PROGRAM_REGISTRY = [
aiObservabilityConfig,
metricsConfig,
slackConnectConfig,
shakespeareConfig,
] as const satisfies readonly ProgramConfig[];

/**
Expand Down Expand Up @@ -112,6 +114,7 @@ export const Program = {
AiObservability: aiObservabilityConfig.id,
Metrics: metricsConfig.id,
SlackConnect: slackConnectConfig.id,
Shakespeare: shakespeareConfig.id,
} as const;

/** Compile-time union of every registered program id. */
Expand Down
65 changes: 65 additions & 0 deletions src/lib/programs/shakespeare/content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Shakespeare learn-deck — portrait, then what the program does, then a
* few lines it might drop into your code. Overrides the generic
* agent-skill deck (`programs/agent-skill/content/index.tsx`) that
* `createSkillProgram` wires up by default.
*/

import { TextRevealMode } from '@ui/tui/primitives/TextBlock';
import type { ContentBlock } from '@ui/tui/primitives/content-types';
import type { WizardStore } from '@ui/tui/store';
import { PORTRAIT_BLOCK } from './portrait.js';

const CLEAR: ContentBlock = { type: 'clear', pause: 1500 };

export const getContentBlocks = (_store?: WizardStore): ContentBlock[] => [
// Scene 1 — portrait
PORTRAIT_BLOCK,

CLEAR,

// Scene 2 — what this program actually does
{
content: 'This one is an internal test, not a PostHog feature.',
pause: 4000,
mode: TextRevealMode.Typewriter,
animationInterval: 24,
},
{
content:
'It installs a single context-mill skill with no SDK and no product logic.',
pause: 5000,
},
{
content:
"Just one line of Shakespeare, dropped into your project's most prominent file.",
pause: 5000,
},
{
content: "It's here to test the skill-to-wizard-program pipeline end to end.",
pause: 5000,
},

CLEAR,

// Scene 3 — a few lines it might choose from
{ content: 'A few of the lines it might pick:', pause: 2500 },

{
content: '"All the world\'s a stage, and all the men and women merely players."',
pause: 5000,
mode: TextRevealMode.SentenceFade,
},

{
content: '"To be, or not to be, that is the question."',
pause: 5000,
mode: TextRevealMode.SentenceFade,
},

{
content: '"We know what we are, but know not what we may be."',
pause: 5000,
mode: TextRevealMode.SentenceFade,
},
];
39 changes: 39 additions & 0 deletions src/lib/programs/shakespeare/content/portrait.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* PORTRAIT_BLOCK — ASCII portrait shown first in the shakespeare Learn
* deck. Fixed at 37 chars wide (14 rows) to fit the LearnCard pane at an
* 80-column terminal — see the pane-width math in `LearnCard.tsx` and the
* same convention self-driving's `PIPELINE_BLOCK` follows. Rendered as
* exact `lines` (not a wrapped string) so word-wrap can't corrupt it.
*/

import { Text } from 'ink';
import { Colors } from '@ui/tui/styles';
import type { ContentBlock } from '@ui/tui/primitives/content-types';

const PORTRAIT_ROWS = [
'%%%%%%%%%%%%%###=+*##%##%%%%%%%%%%%%%',
'%%%%%%%%%%##:*###**=--*#####%%%%%%%%%',
'%%%%%######:#%%%%%%#==:=#########%%%%',
'%%%######-:+##%####*+:-.:=*########%%',
'%#######+=:--+*=--=+=-:-..:**######%%',
'%#####**=--*++*#**#*=::-:..:******###',
'%###*****--+#%**#**+=:.:..:=*+*****##',
'####***+*+=:-==:=**--=#+:.-=++*++*+*#',
'####***+++*+-+**+-::+%*#*--++++*+++*#',
'##****+++++*+.:--.-%%####..:++++++**#',
'##***+++=:####:##%##%#%*:.:..::++==**',
'##****-.::#:.#*.#.##*.:-.-:.::..:--+*',
'%##*=:.=.+=.=..:.-:-:-:-==-=-:=:::==#',
'%##*-.-....+.=-.:.::=+:=+-+:-+=+:*=+#',
];

export const PORTRAIT_BLOCK: ContentBlock = {
type: 'lines',
interval: 50,
pause: 4000,
lines: PORTRAIT_ROWS.map((row, i) => (
<Text key={i} color={Colors.accent}>
{row}
</Text>
)),
};
35 changes: 35 additions & 0 deletions src/lib/programs/shakespeare/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createSkillProgram } from '@lib/programs/agent-skill/index';
import type { ProgramConfig } from '@lib/programs/program-step';
import { getContentBlocks } from './content/index.js';

const SHAKESPEARE_REPORT_FILE = 'posthog-shakespeare-report.md';

const baseConfig = createSkillProgram({
skillId: 'shakespeare',
command: 'shakespeare',
id: 'shakespeare',
description:
'Add a line of Shakespeare to your codebase (internal test only)',
integrationLabel: 'shakespeare',
successMessage: `Shakespeare quote added! View the report at ./${SHAKESPEARE_REPORT_FILE}`,
reportFile: SHAKESPEARE_REPORT_FILE,
docsUrl: 'https://github.com/PostHog/context-mill',
spinnerMessage: 'Consulting the Bard...',
estimatedDurationMinutes: 1,
});

/**
* `wizard shakespeare` — internal test-only program. Installs the
* context-mill `shakespeare` skill (single variant, no framework matching)
* and lets the agent run it end to end. Exists purely to exercise the
* skill-authoring → wizard-program pipeline in isolation; not a real
* PostHog product flow.
*
* Overrides `getContentBlocks` with its own Learn deck (portrait → what
* this program does → a few lines it might pick) instead of the generic
* three-line agent-skill deck `createSkillProgram` wires up by default.
*/
export const shakespeareConfig: ProgramConfig = {
...baseConfig,
getContentBlocks,
};