@agimon-ai/po-help 0.0.0-alpha.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 +73 -0
- package/dist/apiContracts.cjs +17 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +53 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +13 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/server.cjs +323 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +318 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +88 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +763 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +133 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +732 -0
- package/dist/index.mjs.map +1 -0
- package/llms.txt +15 -0
- package/package.json +117 -0
- package/src/prompts/po-develop-native-extension/SKILL.md +63 -0
- package/src/prompts/po-use-chatgpt-instructions/SKILL.md +66 -0
- package/src/prompts/po-use-help/SKILL.md +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["HELP_INDEX_PATH","isRecord"],"sources":["../src/services/llmsContent/index.ts","../src/services/helpActivation/index.ts","../src/services/helpStorage/index.ts","../src/services/llmsResolver/index.ts","../src/services/helpRuntime/index.ts"],"sourcesContent":["import type { DoomHelpSkillDescriptor } from '@agimon-ai/po-core/help';\n\nimport type { ResolvedHelpIndex } from '../../types/help';\n\nexport const MAX_LLMS_BYTES = 1024 * 1024;\nexport const MAX_AGGREGATE_LLMS_BYTES = 4 * MAX_LLMS_BYTES;\n\nconst MARKDOWN_LINK_PATTERN = /!?\\[[^\\]]*\\]\\(\\s*<?([^\\s)>]+)>?(?:\\s+[^)]*)?\\)/gu;\nconst MARKDOWN_REFERENCE_LINK_PATTERN = /^\\s{0,3}\\[[^\\]\\r\\n]+\\]:\\s*<?([^\\s>]+)>?/gmu;\nconst MARKDOWN_AUTOLINK_PATTERN = /<((?:\\.{0,2}\\/|[A-Za-z][A-Za-z0-9+.-]*:)[^<>\\s]+)>/gu;\nconst HTML_LINK_PATTERN = /\\b(?:href|src)\\s*=\\s*[\"']([^\"']+)[\"']/giu;\nconst URI_SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*:/iu;\nconst NESTED_PATH_ENCODING_PATTERN = /%(?:25|2e|2f|3a|5c)/iu;\nconst SAFE_EXTERNAL_SCHEMES = new Set(['http:', 'https:', 'mailto:']);\n\nfunction externalScheme(target: string): string | undefined {\n if (!URI_SCHEME_PATTERN.test(target)) return undefined;\n return target.slice(0, target.indexOf(':') + 1).toLowerCase();\n}\n\nfunction decodeRelativeTarget(rawTarget: string): string {\n let decoded = rawTarget;\n try {\n for (let pass = 0; pass < 2; pass += 1) {\n const next = decodeURIComponent(decoded);\n if (next === decoded) break;\n decoded = next;\n }\n } catch {\n throw new Error(`llms.txt contains an invalid encoded link '${rawTarget}'.`);\n }\n if (NESTED_PATH_ENCODING_PATTERN.test(decoded)) {\n throw new Error(`llms.txt contains an unsafe nested encoding in link '${rawTarget}'.`);\n }\n return decoded;\n}\n\nfunction validateRelativeLink(rawTarget: string): void {\n if (!rawTarget || rawTarget.startsWith('#')) return;\n const rawScheme = externalScheme(rawTarget);\n if (rawScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(rawScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${rawScheme}'.`);\n }\n return;\n }\n\n const decoded = decodeRelativeTarget(rawTarget);\n const decodedScheme = externalScheme(decoded);\n if (decodedScheme) {\n if (!SAFE_EXTERNAL_SCHEMES.has(decodedScheme)) {\n throw new Error(`llms.txt contains unsupported link scheme '${decodedScheme}'.`);\n }\n return;\n }\n const withoutSuffix = decoded.split(/[?#]/u, 1)[0]?.replaceAll('\\\\', '/') ?? '';\n if (withoutSuffix.startsWith('/') || withoutSuffix.split('/').some((segment) => segment === '..')) {\n throw new Error(`llms.txt link '${rawTarget}' escapes the package root.`);\n }\n}\n\nfunction containsUnsafeControl(text: string): boolean {\n for (const character of text) {\n const code = character.codePointAt(0) ?? 0;\n if ((code >= 0 && code <= 8) || code === 11 || code === 12 || (code >= 14 && code <= 31) || code === 127) {\n return true;\n }\n }\n return false;\n}\n\nexport function validateLlmsBytes(bytes: Uint8Array): string {\n if (bytes.byteLength === 0) throw new Error('llms.txt is empty.');\n if (bytes.byteLength > MAX_LLMS_BYTES) throw new Error(`llms.txt exceeds ${MAX_LLMS_BYTES} bytes.`);\n\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n throw new Error('llms.txt is not valid UTF-8.');\n }\n if (text.startsWith('\\uFEFF')) text = text.slice(1);\n if (containsUnsafeControl(text)) throw new Error('llms.txt contains unsafe control bytes.');\n\n const firstContentLine = text\n .split(/\\r?\\n/u)\n .find((line) => line.trim().length > 0)\n ?.trim();\n if (!firstContentLine || !/^#\\s+\\S/u.test(firstContentLine)) {\n throw new Error('llms.txt must begin with a Markdown H1 heading.');\n }\n for (const pattern of [\n MARKDOWN_LINK_PATTERN,\n MARKDOWN_REFERENCE_LINK_PATTERN,\n MARKDOWN_AUTOLINK_PATTERN,\n HTML_LINK_PATTERN,\n ]) {\n for (const match of text.matchAll(pattern)) validateRelativeLink(match[1] ?? '');\n }\n return text;\n}\n\nexport function renderHelpSkillWrapper(descriptor: DoomHelpSkillDescriptor, index: ResolvedHelpIndex): string {\n const name = JSON.stringify(descriptor.name);\n const description = JSON.stringify(descriptor.description);\n const indexPath = JSON.stringify(index.filePath);\n const referenceBase = JSON.stringify(index.referenceBase);\n return `---\\nname: ${name}\\ndescription: ${description}\\n---\\n\\n# Package Help\\n\\nRead the validated package Help index at ${indexPath}.\\nResolve relative links in that index against ${referenceBase}.\\nOpen only the linked documents relevant to the current request, as needed; do not recursively load the whole reference set.\\n`;\n}\n","import {\n DOOM_HELP_MAX_DIAGNOSTIC_LENGTH,\n DOOM_HELP_MAX_DIAGNOSTICS,\n DOOM_HELP_MAX_SKILLS,\n type DoomHelpContribution,\n type DoomHelpDiagnostic,\n type DoomHelpSkill,\n} from '@agimon-ai/po-core/help';\n\nimport type {\n HelpActivationDependencies,\n HelpActivationService,\n HelpRuntimeState,\n ResolvedHelpIndex,\n} from '../../types/help';\nimport { MAX_AGGREGATE_LLMS_BYTES } from '../llmsContent';\n\nconst MAX_RESOLUTION_CONCURRENCY = 4;\nconst FAILURE_MESSAGE = 'No package Help source could be activated.';\nconst CANCELLATION_MESSAGE = 'Help activation was cancelled.';\n\ninterface LoadedSource {\n contribution: DoomHelpContribution;\n index: ResolvedHelpIndex;\n skills: readonly DoomHelpSkill[];\n}\n\ninterface SourceOutcome {\n source: string;\n loaded?: LoadedSource;\n error?: unknown;\n}\n\nexport class HelpActivationError extends Error {\n constructor(message = FAILURE_MESSAGE) {\n super(message);\n this.name = 'HelpActivationError';\n }\n}\n\nfunction cloneContribution(contribution: DoomHelpContribution): DoomHelpContribution {\n return {\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills.map((skill) => ({ ...skill })),\n };\n}\n\nfunction cloneState(state: HelpRuntimeState): HelpRuntimeState {\n return {\n activation: state.activation,\n skills: state.skills.map((skill) => ({ ...skill })),\n diagnostics: state.diagnostics.map((diagnostic) => ({ ...diagnostic })),\n };\n}\n\nfunction diagnostic(source: string, code: string, error: unknown): DoomHelpDiagnostic {\n const raw = error instanceof Error ? error.message : String(error);\n const message = (raw || 'Unknown Help activation failure.').slice(0, DOOM_HELP_MAX_DIAGNOSTIC_LENGTH);\n return { source, code, message };\n}\n\nfunction contributionFingerprint(contributions: readonly DoomHelpContribution[]): string {\n return JSON.stringify(\n contributions.map((contribution) => ({\n source: contribution.source,\n moduleUrl: contribution.moduleUrl,\n skills: contribution.skills,\n })),\n );\n}\n\nexport class DefaultHelpActivationService implements HelpActivationService {\n private readonly dependencies: HelpActivationDependencies;\n private readonly listeners = new Set<(state: HelpRuntimeState) => void>();\n private contributions: DoomHelpContribution[] = [];\n private fingerprint = '[]';\n private state: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private settledState: HelpRuntimeState = { activation: 'inactive', skills: [], diagnostics: [] };\n private generation = 0;\n private controller: AbortController | undefined;\n private disposed = false;\n\n constructor(dependencies: HelpActivationDependencies) {\n this.dependencies = dependencies;\n }\n\n getState(): HelpRuntimeState {\n return cloneState(this.state);\n }\n\n replaceContributions(contributions: readonly DoomHelpContribution[]): void {\n if (this.disposed) return;\n const next = contributions.map(cloneContribution).sort((left, right) => left.source.localeCompare(right.source));\n const fingerprint = contributionFingerprint(next);\n if (fingerprint === this.fingerprint) return;\n const previous = new Map(this.contributions.map((entry) => [entry.source, contributionFingerprint([entry])]));\n const retained = new Set(\n next\n .filter((entry) => previous.get(entry.source) === contributionFingerprint([entry]))\n .map((entry) => entry.source),\n );\n // A refresh may retain unchanged owners, never withdrawn or replaced ones.\n // Prune the rollback snapshot too, so cancellation cannot resurrect them.\n const skills = this.settledState.skills.filter((entry) => retained.has(entry.source));\n const diagnostics = this.settledState.diagnostics.filter((entry) => !entry.source || retained.has(entry.source));\n this.settledState = {\n activation: skills.length === 0 ? 'inactive' : diagnostics.length > 0 ? 'degraded' : 'active',\n skills,\n diagnostics,\n };\n this.contributions = next;\n this.fingerprint = fingerprint;\n if (this.state.activation !== 'inactive') {\n void this.activate().catch((error: unknown) => {\n // Activation failures publish a bounded settled state before rejecting.\n // Only unexpected implementation failures need an out-of-band report.\n if (error instanceof HelpActivationError) return;\n this.dependencies.onBackgroundError(error);\n });\n }\n }\n\n subscribe(listener: (state: HelpRuntimeState) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private publish(state: HelpRuntimeState): HelpRuntimeState {\n this.state = cloneState(state);\n if (state.activation !== 'activating') this.settledState = cloneState(state);\n this.dependencies.publisher.publish(this.state);\n for (const listener of this.listeners) listener(cloneState(this.state));\n return this.getState();\n }\n\n private async loadSources(signal: AbortSignal): Promise<SourceOutcome[]> {\n const contributions = this.contributions;\n const outcomes: SourceOutcome[] = Array.from({ length: contributions.length });\n let cursor = 0;\n const worker = async (): Promise<void> => {\n while (cursor < contributions.length) {\n const index = cursor;\n cursor += 1;\n const contribution = contributions[index];\n if (!contribution) return;\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n try {\n const resolved = await this.dependencies.resolver.resolve(contribution, signal);\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n const skills = await this.dependencies.materializer.materialize(contribution, resolved, signal);\n outcomes[index] = { source: contribution.source, loaded: { contribution, index: resolved, skills } };\n } catch (error) {\n if (signal.aborted) throw new HelpActivationError(CANCELLATION_MESSAGE);\n outcomes[index] = { source: contribution.source, error };\n }\n }\n };\n const count = Math.min(MAX_RESOLUTION_CONCURRENCY, contributions.length);\n await Promise.all(Array.from({ length: count }, () => worker()));\n return outcomes;\n }\n\n async activate(externalSignal?: AbortSignal): Promise<HelpRuntimeState> {\n if (this.disposed) throw new HelpActivationError('Help runtime is disposed.');\n this.controller?.abort('Help activation generation replaced.');\n const controller = new AbortController();\n this.controller = controller;\n const generation = ++this.generation;\n const abortFromExternal = () => controller.abort(externalSignal?.reason);\n externalSignal?.addEventListener('abort', abortFromExternal, { once: true });\n if (externalSignal?.aborted) abortFromExternal();\n\n const settledState = cloneState(this.settledState);\n this.publish({ activation: 'activating', skills: settledState.skills, diagnostics: settledState.diagnostics });\n try {\n const outcomes = await this.loadSources(controller.signal);\n if (controller.signal.aborted || generation !== this.generation) {\n throw new HelpActivationError(CANCELLATION_MESSAGE);\n }\n\n const diagnostics: DoomHelpDiagnostic[] = [];\n const loaded: LoadedSource[] = [];\n let aggregateBytes = 0;\n for (const outcome of outcomes) {\n if (!outcome) continue;\n if (outcome.error || !outcome.loaded) {\n diagnostics.push(diagnostic(outcome.source, 'HELP_SOURCE_FAILED', outcome.error));\n continue;\n }\n if (aggregateBytes + outcome.loaded.index.byteLength > MAX_AGGREGATE_LLMS_BYTES) {\n diagnostics.push(\n diagnostic(outcome.source, 'HELP_AGGREGATE_LIMIT', 'The aggregate llms.txt byte limit was exceeded.'),\n );\n continue;\n }\n aggregateBytes += outcome.loaded.index.byteLength;\n loaded.push(outcome.loaded);\n }\n\n const skills: DoomHelpSkill[] = [];\n const names = new Set<string>();\n for (const source of loaded) {\n for (const skill of source.skills) {\n if (skills.length >= DOOM_HELP_MAX_SKILLS) {\n diagnostics.push(\n diagnostic(source.contribution.source, 'HELP_SKILL_LIMIT', 'The Help skill limit was reached.'),\n );\n break;\n }\n if (names.has(skill.name)) {\n diagnostics.push(\n diagnostic(\n source.contribution.source,\n 'HELP_SKILL_COLLISION',\n `Help skill '${skill.name}' was already provided by an earlier package source.`,\n ),\n );\n continue;\n }\n names.add(skill.name);\n skills.push({ ...skill });\n }\n }\n\n const boundedDiagnostics = diagnostics.slice(0, DOOM_HELP_MAX_DIAGNOSTICS);\n if (skills.length === 0) {\n this.publish({ activation: 'inactive', skills: [], diagnostics: boundedDiagnostics });\n throw new HelpActivationError();\n }\n return this.publish({\n activation: boundedDiagnostics.length > 0 ? 'degraded' : 'active',\n skills,\n diagnostics: boundedDiagnostics,\n });\n } catch (error) {\n if (generation === this.generation && this.state.activation === 'activating') this.publish(settledState);\n throw error;\n } finally {\n externalSignal?.removeEventListener('abort', abortFromExternal);\n if (this.controller === controller) this.controller = undefined;\n }\n }\n\n deactivate(): HelpRuntimeState {\n this.generation += 1;\n this.controller?.abort('Help deactivated.');\n this.controller = undefined;\n return this.publish({ activation: 'inactive', skills: [], diagnostics: [] });\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.deactivate();\n this.disposed = true;\n this.listeners.clear();\n }\n}\n","import { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport type { DoomHelpContribution, DoomHelpSkill } from '@agimon-ai/po-core/help';\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\n\nimport type { HelpPackageIdentity, HelpSkillMaterializer, ResolvedHelpIndex } from '../../types/help';\nimport { renderHelpSkillWrapper } from '../llmsContent';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst HELP_INDEX_PATH = 'llms.txt';\nconst CACHE_SCHEMA_VERSION = 1;\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst COMPLETION_FILE = '.complete';\nconst CACHE_METADATA_FILE = 'metadata.json';\nconst WRAPPER_DIRECTORY = 'wrappers';\nconst SKILL_FILE = 'SKILL.md';\nconst EXACT_SEMVER_PATTERN =\n /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/u;\nconst NPM_PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\\/)?[a-z0-9][a-z0-9._~-]*$/u;\n\ninterface CacheMetadata {\n schemaVersion: typeof CACHE_SCHEMA_VERSION;\n source: string;\n version: string;\n path: typeof HELP_INDEX_PATH;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nexport interface CachedHelpIndex {\n bytes: Uint8Array;\n filePath: string;\n integrity: string;\n digest: string;\n referenceBase: string;\n}\n\nfunction assertNotAborted(signal: AbortSignal): void {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isContained(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));\n}\n\nfunction readManifest(filePath: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, 'utf8')) as unknown;\n } catch (error) {\n throw new Error(\n `Cannot read Help package manifest at ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!isRecord(parsed)) throw new Error(`Help package manifest at ${filePath} must contain an object.`);\n return parsed;\n}\n\nexport function resolveHelpPackageIdentity(moduleUrl: string, expectedSource: string): HelpPackageIdentity {\n if (!NPM_PACKAGE_NAME_PATTERN.test(expectedSource)) {\n throw new Error(`Help source '${expectedSource}' must be a valid lowercase npm package name.`);\n }\n let modulePath: string;\n try {\n const url = new URL(moduleUrl);\n if (url.protocol !== 'file:') throw new Error(`Help module URL must use file:, received ${url.protocol}`);\n modulePath = fs.realpathSync(fileURLToPath(url));\n } catch (error) {\n throw new Error(\n `Invalid Help contributor module URL '${moduleUrl}': ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!fs.lstatSync(modulePath).isFile())\n throw new Error(`Help contributor module is not a regular file: ${modulePath}`);\n\n let directory = path.dirname(modulePath);\n while (true) {\n const manifestPath = path.join(directory, PACKAGE_MANIFEST);\n if (fs.existsSync(manifestPath)) {\n const manifest = readManifest(manifestPath);\n const source = manifest.name;\n const version = manifest.version;\n if (source !== expectedSource) {\n throw new Error(`Help source '${expectedSource}' does not match nearest package '${String(source)}'.`);\n }\n if (typeof version !== 'string' || !EXACT_SEMVER_PATTERN.test(version)) {\n throw new Error(`Help package '${expectedSource}' must declare an exact semantic version.`);\n }\n const packageRoot = fs.realpathSync(directory);\n if (!isContained(packageRoot, modulePath))\n throw new Error('Help contributor module escapes its resolved package root.');\n return { source: expectedSource, version, packageRoot, modulePath };\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n throw new Error(`Cannot find a package manifest for Help contributor ${modulePath}.`);\n}\n\nexport function defaultHelpCacheRoot(homeDirectory = os.homedir()): string {\n return path.join(poHomeDirectory(homeDirectory), 'llms-cache');\n}\n\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nfunction parseCacheMetadata(value: unknown, identity: HelpPackageIdentity): CacheMetadata | undefined {\n if (!isRecord(value)) return undefined;\n if (\n value.schemaVersion !== CACHE_SCHEMA_VERSION ||\n value.source !== identity.source ||\n value.version !== identity.version ||\n value.path !== HELP_INDEX_PATH ||\n typeof value.integrity !== 'string' ||\n typeof value.digest !== 'string' ||\n typeof value.referenceBase !== 'string'\n ) {\n return undefined;\n }\n return value as unknown as CacheMetadata;\n}\n\nfunction regularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nexport class HelpIndexCache {\n readonly root: string;\n\n constructor(root = defaultHelpCacheRoot()) {\n this.root = root;\n }\n\n entryDirectory(identity: HelpPackageIdentity): string {\n const key = sha256Hex(`${identity.source}\\0${identity.version}\\0${HELP_INDEX_PATH}`);\n return path.join(this.root, key);\n }\n\n discard(identity: HelpPackageIdentity): void {\n fs.rmSync(this.entryDirectory(identity), { recursive: true, force: true });\n }\n\n read(identity: HelpPackageIdentity): CachedHelpIndex | undefined {\n const directory = this.entryDirectory(identity);\n const completionPath = path.join(directory, COMPLETION_FILE);\n const indexPath = path.join(directory, HELP_INDEX_PATH);\n const metadataPath = path.join(directory, CACHE_METADATA_FILE);\n if (!regularFile(completionPath) || !regularFile(indexPath) || !regularFile(metadataPath)) return undefined;\n try {\n const metadata = parseCacheMetadata(JSON.parse(fs.readFileSync(metadataPath, 'utf8')) as unknown, identity);\n if (!metadata) return undefined;\n const bytes = fs.readFileSync(indexPath);\n if (sha256Hex(bytes) !== metadata.digest) return undefined;\n if (fs.readFileSync(completionPath, 'utf8').trim() !== metadata.digest) return undefined;\n return {\n bytes,\n filePath: indexPath,\n integrity: metadata.integrity,\n digest: metadata.digest,\n referenceBase: metadata.referenceBase,\n };\n } catch {\n return undefined;\n }\n }\n\n publish(\n identity: HelpPackageIdentity,\n bytes: Uint8Array,\n integrity: string,\n referenceBase: string,\n signal: AbortSignal,\n ): CachedHelpIndex {\n assertNotAborted(signal);\n const existing = this.read(identity);\n if (existing) return existing;\n const directory = this.entryDirectory(identity);\n fs.mkdirSync(this.root, { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n const digest = sha256Hex(bytes);\n const metadata: CacheMetadata = {\n schemaVersion: CACHE_SCHEMA_VERSION,\n source: identity.source,\n version: identity.version,\n path: HELP_INDEX_PATH,\n integrity,\n digest,\n referenceBase,\n };\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, HELP_INDEX_PATH), bytes, { mode: PRIVATE_FILE_MODE });\n fs.writeFileSync(path.join(temporary, CACHE_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\\n`, {\n mode: PRIVATE_FILE_MODE,\n });\n assertNotAborted(signal);\n fs.writeFileSync(path.join(temporary, COMPLETION_FILE), `${digest}\\n`, { mode: PRIVATE_FILE_MODE });\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n const winner = this.read(identity);\n if (winner) return winner;\n throw error;\n }\n return {\n bytes: Uint8Array.from(bytes),\n filePath: path.join(directory, HELP_INDEX_PATH),\n integrity,\n digest,\n referenceBase,\n };\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n}\n\nexport class DefaultHelpSkillMaterializer implements HelpSkillMaterializer {\n constructor(private readonly cacheRoot = defaultHelpCacheRoot()) {}\n\n async materialize(\n contribution: DoomHelpContribution,\n index: ResolvedHelpIndex,\n signal: AbortSignal,\n ): Promise<readonly DoomHelpSkill[]> {\n const skills: DoomHelpSkill[] = [];\n for (const descriptor of contribution.skills) {\n assertNotAborted(signal);\n const key = sha256Hex(\n `${index.identity.source}\\0${index.identity.version}\\0${descriptor.name}\\0${descriptor.description}\\0${index.digest}`,\n );\n const directory = path.join(this.cacheRoot, WRAPPER_DIRECTORY, key);\n const filePath = path.join(directory, SKILL_FILE);\n const content = renderHelpSkillWrapper(descriptor, index);\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) {\n fs.mkdirSync(path.dirname(directory), { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n if (fs.existsSync(directory)) fs.rmSync(directory, { recursive: true, force: true });\n const temporary = `${directory}.${process.pid}.${randomUUID()}.tmp`;\n try {\n fs.mkdirSync(temporary, { mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(path.join(temporary, SKILL_FILE), content, { mode: PRIVATE_FILE_MODE });\n assertNotAborted(signal);\n try {\n fs.renameSync(temporary, directory);\n } catch (error) {\n if (!regularFile(filePath) || fs.readFileSync(filePath, 'utf8') !== content) throw error;\n }\n } finally {\n fs.rmSync(temporary, { recursive: true, force: true });\n }\n }\n skills.push({\n source: contribution.source,\n name: descriptor.name,\n description: descriptor.description,\n filePath,\n baseDir: directory,\n });\n }\n return skills;\n }\n}\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { DoomHelpContribution } from '@agimon-ai/po-core/help';\n\nimport type { HelpFetch, HelpFetchResponse, HelpIndexResolver, ResolvedHelpIndex } from '../../types/help';\nimport { HelpIndexCache, resolveHelpPackageIdentity, sha256Hex } from '../helpStorage';\nimport { MAX_LLMS_BYTES, validateLlmsBytes } from '../llmsContent';\n\nconst HELP_INDEX_PATH = 'llms.txt';\nconst UNPKG_ORIGIN = 'https://unpkg.com';\nconst DEFAULT_FETCH_TIMEOUT_MS = 5_000;\nconst MAX_METADATA_BYTES = 512 * 1024;\nconst MAX_REDIRECTS = 3;\nconst SRI_PATTERN = /^sha256-([A-Za-z0-9+/]+={0,2})$/u;\n\ninterface UnpkgMetadataFile {\n path: string;\n size?: number;\n integrity: string;\n}\n\nexport interface DefaultHelpIndexResolverOptions {\n cache?: HelpIndexCache;\n fetch?: HelpFetch;\n timeoutMs?: number;\n}\n\nfunction defaultFetch(input: string, init: { signal: AbortSignal; redirect: 'manual' }): Promise<HelpFetchResponse> {\n return fetch(input, init) as unknown as Promise<HelpFetchResponse>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isRegularFile(filePath: string): boolean {\n try {\n const metadata = fs.lstatSync(filePath);\n return metadata.isFile() && !metadata.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nfunction unpkgPackagePath(source: string, version: string): string {\n const encoded = source\n .split('/')\n .map((segment) =>\n segment.startsWith('@') ? `@${encodeURIComponent(segment.slice(1))}` : encodeURIComponent(segment),\n )\n .join('/');\n return `${encoded}@${encodeURIComponent(version)}`;\n}\n\nfunction exactUnpkgBase(source: string, version: string): string {\n return `${UNPKG_ORIGIN}/${unpkgPackagePath(source, version)}/`;\n}\n\nfunction contentLength(response: HelpFetchResponse): number | undefined {\n const raw = response.headers.get('content-length');\n if (!raw) return undefined;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nfunction timeoutSignal(parent: AbortSignal, timeoutMs: number): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abort = () => controller.abort(parent.reason);\n parent.addEventListener('abort', abort, { once: true });\n const timer = setTimeout(() => controller.abort(new Error('Help download timed out.')), timeoutMs);\n if (parent.aborted) abort();\n return {\n signal: controller.signal,\n dispose() {\n clearTimeout(timer);\n parent.removeEventListener('abort', abort);\n },\n };\n}\n\nasync function fetchExact(fetcher: HelpFetch, initialUrl: string, signal: AbortSignal): Promise<HelpFetchResponse> {\n let url = initialUrl;\n const expected = new URL(initialUrl);\n for (let redirect = 0; redirect <= MAX_REDIRECTS; redirect += 1) {\n const response = await fetcher(url, { signal, redirect: 'manual' });\n if (response.status < 300 || response.status >= 400) return response;\n const location = response.headers.get('location');\n if (!location) throw new Error(`Unpkg redirected ${url} without a location.`);\n const next = new URL(location, url);\n if (next.origin !== UNPKG_ORIGIN || next.pathname !== expected.pathname || next.search !== expected.search) {\n throw new Error(`Unpkg redirect escaped the exact package/version path: ${next.href}`);\n }\n url = next.href;\n }\n throw new Error(`Unpkg exceeded ${MAX_REDIRECTS} redirects.`);\n}\n\nfunction parseMetadata(text: string): UnpkgMetadataFile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n throw new Error('Unpkg metadata is not valid JSON.');\n }\n if (!isRecord(parsed) || !Array.isArray(parsed.files)) throw new Error('Unpkg metadata has no files list.');\n const match = parsed.files.find((entry) => isRecord(entry) && entry.path === `/${HELP_INDEX_PATH}`);\n if (!isRecord(match) || typeof match.integrity !== 'string') {\n throw new Error(`Unpkg package does not publish /${HELP_INDEX_PATH}.`);\n }\n const size = typeof match.size === 'number' ? match.size : undefined;\n if (size !== undefined && (!Number.isSafeInteger(size) || size < 0 || size > MAX_LLMS_BYTES)) {\n throw new Error(`Unpkg /${HELP_INDEX_PATH} exceeds the Help size limit.`);\n }\n if (!SRI_PATTERN.test(match.integrity)) throw new Error('Unpkg llms.txt metadata does not contain SHA-256 SRI.');\n return { path: match.path as string, ...(size === undefined ? {} : { size }), integrity: match.integrity };\n}\n\nfunction verifySri(bytes: Uint8Array, integrity: string): void {\n const expected = SRI_PATTERN.exec(integrity)?.[1];\n if (!expected) throw new Error('Invalid llms.txt SRI metadata.');\n const actual = createHash('sha256').update(bytes).digest('base64');\n if (actual !== expected) throw new Error('Downloaded llms.txt failed SRI verification.');\n}\n\nexport class DefaultHelpIndexResolver implements HelpIndexResolver {\n private readonly cache: HelpIndexCache;\n private readonly fetcher: HelpFetch;\n private readonly timeoutMs: number;\n\n constructor(options: DefaultHelpIndexResolverOptions = {}) {\n this.cache = options.cache ?? new HelpIndexCache();\n this.fetcher = options.fetch ?? defaultFetch;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n }\n\n async resolve(contribution: DoomHelpContribution, signal: AbortSignal): Promise<ResolvedHelpIndex> {\n if (signal.aborted) throw new Error('Help activation was cancelled.');\n const identity = resolveHelpPackageIdentity(contribution.moduleUrl, contribution.source);\n const localPath = path.join(identity.packageRoot, HELP_INDEX_PATH);\n if (fs.existsSync(localPath)) {\n if (!isRegularFile(localPath)) throw new Error(`Bundled ${HELP_INDEX_PATH} must be a regular file.`);\n const bytes = fs.readFileSync(localPath);\n validateLlmsBytes(bytes);\n return {\n identity,\n location: 'local',\n filePath: localPath,\n referenceBase: identity.packageRoot,\n byteLength: bytes.byteLength,\n digest: sha256Hex(bytes),\n };\n }\n\n const cached = this.cache.read(identity);\n if (cached) {\n try {\n validateLlmsBytes(cached.bytes);\n return {\n identity,\n location: 'cache',\n filePath: cached.filePath,\n referenceBase: cached.referenceBase,\n byteLength: cached.bytes.byteLength,\n digest: cached.digest,\n };\n } catch {\n this.cache.discard(identity);\n }\n }\n\n const timed = timeoutSignal(signal, this.timeoutMs);\n try {\n const referenceBase = exactUnpkgBase(identity.source, identity.version);\n const metadataResponse = await fetchExact(this.fetcher, `${referenceBase}?meta`, timed.signal);\n const metadataLength = contentLength(metadataResponse);\n if (metadataLength !== undefined && metadataLength > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n if (!metadataResponse.ok) throw new Error(`Unpkg metadata request failed with HTTP ${metadataResponse.status}.`);\n const metadataText = await metadataResponse.text();\n if (Buffer.byteLength(metadataText, 'utf8') > MAX_METADATA_BYTES) {\n throw new Error('Unpkg metadata exceeds the Help metadata size limit.');\n }\n const metadata = parseMetadata(metadataText);\n const indexResponse = await fetchExact(this.fetcher, `${referenceBase}${HELP_INDEX_PATH}`, timed.signal);\n const indexLength = contentLength(indexResponse);\n if (indexLength !== undefined && indexLength > MAX_LLMS_BYTES) {\n throw new Error(`Downloaded ${HELP_INDEX_PATH} exceeds ${MAX_LLMS_BYTES} bytes.`);\n }\n if (!indexResponse.ok) throw new Error(`Unpkg llms.txt request failed with HTTP ${indexResponse.status}.`);\n const bytes = new Uint8Array(await indexResponse.arrayBuffer());\n validateLlmsBytes(bytes);\n verifySri(bytes, metadata.integrity);\n const published = this.cache.publish(identity, bytes, metadata.integrity, referenceBase, timed.signal);\n return {\n identity,\n location: 'remote',\n filePath: published.filePath,\n referenceBase: published.referenceBase,\n byteLength: published.bytes.byteLength,\n digest: published.digest,\n };\n } finally {\n timed.dispose();\n }\n }\n}\n","import type { DoomHelpContribution, DoomHelpService } from '@agimon-ai/po-core/help';\n\nimport type { HelpFetch } from '../../types/help';\nimport { DefaultHelpActivationService } from '../helpActivation';\nimport { DefaultHelpSkillMaterializer, defaultHelpCacheRoot, HelpIndexCache } from '../helpStorage';\nimport { DefaultHelpIndexResolver } from '../llmsResolver';\n\nexport interface HelpRuntimeOptions {\n cacheRoot?: string;\n fetch?: HelpFetch;\n timeoutMs?: number;\n onBackgroundError?(error: unknown): void;\n}\n\nexport interface HelpRuntimeComposition {\n activation: DefaultHelpActivationService;\n dispose(): void;\n}\n\nfunction reportAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error instanceof Error ? error : new Error(String(error));\n });\n}\n\nexport function createHelpRuntime(service: DoomHelpService, options: HelpRuntimeOptions = {}): HelpRuntimeComposition {\n const cacheRoot = options.cacheRoot ?? defaultHelpCacheRoot();\n const cache = new HelpIndexCache(cacheRoot);\n const activation = new DefaultHelpActivationService({\n resolver: new DefaultHelpIndexResolver({ cache, fetch: options.fetch, timeoutMs: options.timeoutMs }),\n materializer: new DefaultHelpSkillMaterializer(cacheRoot),\n publisher: { publish: (snapshot) => service.publish(snapshot) },\n onBackgroundError(error) {\n if (options.onBackgroundError) options.onBackgroundError(error);\n else reportAsync(error);\n },\n });\n const synchronize = (contributions: readonly DoomHelpContribution[]): void => {\n activation.replaceContributions(contributions);\n };\n const unsubscribe = service.subscribeContributions((contributions) => synchronize(contributions));\n synchronize(service.listContributions());\n let disposed = false;\n return {\n activation,\n dispose() {\n if (disposed) return;\n disposed = true;\n unsubscribe();\n activation.dispose();\n },\n };\n}\n"],"mappings":"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"}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Doom Pi Help
|
|
2
|
+
|
|
3
|
+
Activation-gated, package-owned guidance for Doom Pi parent sessions.
|
|
4
|
+
|
|
5
|
+
## Resources
|
|
6
|
+
|
|
7
|
+
- [Package README](./README.md): Public entrypoints, activation model, security guarantees, and development commands.
|
|
8
|
+
|
|
9
|
+
## How to use
|
|
10
|
+
|
|
11
|
+
- [po-use-help](./src/prompts/po-use-help/SKILL.md): Activate package guidance, load exact-version skills, and diagnose unavailable or conflicting contributions.
|
|
12
|
+
|
|
13
|
+
- [po-use-chatgpt-instructions](./src/prompts/po-use-chatgpt-instructions/SKILL.md): Print paste-ready code-mode instructions with all repository rules.
|
|
14
|
+
|
|
15
|
+
- [po-develop-native-extension](./src/prompts/po-develop-native-extension/SKILL.md): Add phone UI to a Po package that mirrors the cockpit, then approve and verify it.
|
package/package.json
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agimon-ai/po-help",
|
|
3
|
+
"version": "0.0.0-alpha.0",
|
|
4
|
+
"description": "Activation-gated package guidance and help skills for Po and Pi extensions.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent-documentation",
|
|
7
|
+
"ai",
|
|
8
|
+
"coding-agent",
|
|
9
|
+
"developer-tools",
|
|
10
|
+
"help-system",
|
|
11
|
+
"pi-coding-agent",
|
|
12
|
+
"pi-extension",
|
|
13
|
+
"pi-package",
|
|
14
|
+
"po",
|
|
15
|
+
"skills"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://agimon.ai",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/AgiFlow/po/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Vuong Ngo",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/AgiFlow/po.git",
|
|
26
|
+
"directory": "packages/minor/po-help"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"llms.txt",
|
|
31
|
+
"src/prompts",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"package.json"
|
|
35
|
+
],
|
|
36
|
+
"type": "module",
|
|
37
|
+
"main": "./dist/index.cjs",
|
|
38
|
+
"module": "./dist/index.mjs",
|
|
39
|
+
"types": "./dist/index.d.mts",
|
|
40
|
+
"jsnext:main": "./dist/index.mjs",
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./dist/index.d.mts",
|
|
44
|
+
"import": "./dist/index.mjs",
|
|
45
|
+
"require": "./dist/index.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./extensions/server": {
|
|
48
|
+
"types": "./dist/extensions/server.d.mts",
|
|
49
|
+
"import": "./dist/extensions/server.mjs",
|
|
50
|
+
"require": "./dist/extensions/server.cjs"
|
|
51
|
+
},
|
|
52
|
+
"./extensions/web": {
|
|
53
|
+
"import": "./dist/extensions/web.mjs"
|
|
54
|
+
},
|
|
55
|
+
"./package.json": "./package.json"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@agimon-ai/po-core": "0.0.0-alpha.0",
|
|
62
|
+
"@agimon-ai/po-minor-mode": "0.0.0-alpha.0",
|
|
63
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.0",
|
|
64
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
65
|
+
"typebox": "1.3.34"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@agimon-ai/po-build": "0.0.0-alpha.0",
|
|
69
|
+
"@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.0-alpha.0",
|
|
70
|
+
"@earendil-works/pi-coding-agent": "1.0.2",
|
|
71
|
+
"@types/node": "26.6.4",
|
|
72
|
+
"@types/react": "19.3.0",
|
|
73
|
+
"@vitest/coverage-v8": "5.0.3",
|
|
74
|
+
"react": "19.3.0",
|
|
75
|
+
"react-dom": "19.3.0",
|
|
76
|
+
"tsdown": "0.23.0",
|
|
77
|
+
"typescript": "7.0.2",
|
|
78
|
+
"vitest": "5.0.3"
|
|
79
|
+
},
|
|
80
|
+
"peerDependencies": {
|
|
81
|
+
"@earendil-works/pi-coding-agent": "1.0.2"
|
|
82
|
+
},
|
|
83
|
+
"peerDependenciesMeta": {
|
|
84
|
+
"@earendil-works/pi-coding-agent": {
|
|
85
|
+
"optional": true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"engines": {
|
|
89
|
+
"node": ">=24"
|
|
90
|
+
},
|
|
91
|
+
"poServer": {
|
|
92
|
+
"entry": "./generated/server.ts",
|
|
93
|
+
"dist": "./dist/extensions/server.mjs",
|
|
94
|
+
"scopes": [
|
|
95
|
+
"session"
|
|
96
|
+
],
|
|
97
|
+
"contracts": {
|
|
98
|
+
"entry": "./src/exports/apiContracts.ts",
|
|
99
|
+
"dist": "./dist/apiContracts.mjs"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"poWeb": {
|
|
103
|
+
"pluginId": "help",
|
|
104
|
+
"channels": [],
|
|
105
|
+
"client": "./dist/extensions/web.mjs",
|
|
106
|
+
"scopes": [
|
|
107
|
+
"session"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"scripts": {
|
|
111
|
+
"build": "tsdown",
|
|
112
|
+
"test": "vitest --run",
|
|
113
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.web.json",
|
|
114
|
+
"lint": "oxlint . && oxfmt . --check",
|
|
115
|
+
"fixcode": "oxlint . --fix && oxfmt ."
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: po-develop-native-extension
|
|
3
|
+
description: Add or change a Po package's phone UI (.native files, native templates) so it mirrors the cockpit, passes the native build, and is approved and verified before it ships.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Develop a native extension
|
|
7
|
+
|
|
8
|
+
Use this when a Po package needs UI in the Po phone app (`packages/clients/po-native`): a tool card, an activity group or fill, a tab, a channel, a settings section, or a phone layout. The full design approach is in `docs/native-design.md` and the routing rules in `docs/extension-layout.md` (section "The native platform") of the Po repository. Read both before changing code when they are available.
|
|
9
|
+
|
|
10
|
+
## Start from the cockpit
|
|
11
|
+
|
|
12
|
+
Every native surface mirrors a cockpit surface. Find the web component or story it corresponds to and the data it reads, and keep that data, copy, colour roles and surfaces. Change only what a phone needs: one column, 44 point targets, stacks, tabs and sheets instead of panes and popovers, and no keyboard hints or hover states. Where the cockpit draws an outline-only card, do not add a fill.
|
|
13
|
+
|
|
14
|
+
Share state, not markup. Import DOM-free models from `@agimon-ai/po-web-dashboard/core` when the app does; inside a package's `.native` file import only the host modules listed below.
|
|
15
|
+
|
|
16
|
+
Place phone UI by what it is:
|
|
17
|
+
|
|
18
|
+
- Something one session owns, such as activity, context or options: a bottom sheet or a pushed screen from that session, never a tab.
|
|
19
|
+
- An activity group's detail: a pushed stack screen that keeps the composer. A "Launch ..." action: a bottom sheet with the form.
|
|
20
|
+
- A whole phone layout: a native template (below).
|
|
21
|
+
|
|
22
|
+
## Wire the package
|
|
23
|
+
|
|
24
|
+
1. Add files under `src/extensions/**/(frontend)/<surface>/` with the `.native.ts` or `.native.tsx` suffix. The native target reads `tool/`, `tab/`, `slot/`, `fill/`, `channel/`, `activity-group/`, `setting/`, `lifecycle/` (`start.native` only), `template/` and `store/`. An unsuffixed file never reaches the phone.
|
|
25
|
+
2. Default-export one definer from `@agimon-ai/po-core/native` (`defineFill`, `defineToolRenderer`, `defineActivityGroup`, `defineNativeTemplate`, ...). Put shared components in a private `_lib` or `_components` folder.
|
|
26
|
+
3. Import only: `react`, `react/jsx-runtime`, `react-native`, `react-native-unistyles`, `@tanstack/store`, `@agimon-ai/po-core/native` and `@agimon-ai/po-native-components`. Anything else fails the native build or the app's module map. Relative imports are bundled, so they may not reach the DOM or another package either.
|
|
27
|
+
4. Give the package `tsconfig.native.json` (no DOM lib) including `src/types/unistyles.native.d.ts`, `src/extensions/**/(frontend)/**/*.native.*` and `generated/native.ts`. Exclude `src/**/*.native.*` from `tsconfig.json`, `**/*.native.*` from `tsconfig.web.json`, and add `tsc --noEmit -p tsconfig.native.json` to `typecheck`. Copy `layers/task/po-task` when unsure.
|
|
28
|
+
5. Add dev dependencies `@agimon-ai/po-native-components` (`workspace:*`), `react-native`, `react-native-unistyles` and `@babel/core`, at the versions po-task uses.
|
|
29
|
+
6. Build. po-build writes `generated/native.ts`, `dist/extensions/native.mjs`, the `./extensions/native` export and the `poNative` manifest block. Do not edit those by hand.
|
|
30
|
+
|
|
31
|
+
## Style it
|
|
32
|
+
|
|
33
|
+
- `StyleSheet.create((theme, rt) => ...)` in the same file as the components that use it, colours from `theme.colors`, fonts through `fontOf(theme.fontFamily.sans)`.
|
|
34
|
+
- Compute alpha mixes (`withAlpha`) in render with `useUnistyles()`, not inside `StyleSheet.create`.
|
|
35
|
+
- Use components from `@agimon-ai/po-native-components` before writing new ones. If an icon is missing, add it to the native set under the web library's name rather than drawing one inline.
|
|
36
|
+
- Running is yellow, failed is red, waiting for the person is rose. Rose never signals an error.
|
|
37
|
+
|
|
38
|
+
## Native templates
|
|
39
|
+
|
|
40
|
+
A phone layout is `template/<name>.native.ts`:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { defineNativeTemplate } from '@agimon-ai/po-core/native';
|
|
44
|
+
|
|
45
|
+
export default defineNativeTemplate({
|
|
46
|
+
label: 'Example',
|
|
47
|
+
description: 'What this phone layout is for.',
|
|
48
|
+
contractVersion: 1,
|
|
49
|
+
screens: { sessions: ExampleSessions },
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`sessions` receives `{ workspaces, openSession }` with the cockpit rail's data. The app keeps pairing, navigation, tabs, headers and Home. `native.template` in `.po/config.yaml` selects a layout; otherwise the app's bundled Advanced is used. A screen that throws falls back to the built-in one.
|
|
54
|
+
|
|
55
|
+
## Design, approve, verify
|
|
56
|
+
|
|
57
|
+
1. Write a story first: `<Component>.native.stories.tsx` beside the component, tagged `style-system`, `mockup` and `native`, using the shared fixtures from `@agimon-ai/po-core/webTesting` (`slotPropsFixture`, `defaultRailWorkspaces`, `railSession`).
|
|
58
|
+
2. Render it light and dark with `pnpm exec style-system get-ui-component -c '<title>' -a packages/clients/po-native -s <Story>`. The native preset pins dark, so a light story sets the theme with `UnistylesRuntime.setTheme('light')` after `setAdaptiveThemes(false)`.
|
|
59
|
+
3. Show the renders and wait for an explicit yes. Silence or your own review is not approval. Keep approved copies with the approval note in the repository's gitignored evidence folder.
|
|
60
|
+
4. Build to match the approved story. Put logic worth testing in a module without React Native imports and test it.
|
|
61
|
+
5. Run the package's lint, typecheck, test and build targets, then check the screen in a Release build on a simulator or device. Report source checks, rendered appearance and device behaviour separately, and say what you did not verify.
|
|
62
|
+
|
|
63
|
+
Never leave a diagnostic on screen. Release builds drop `console` output, so debug with a Debug build and Metro, then remove every probe before reporting.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: po-use-chatgpt-instructions
|
|
3
|
+
description: 'Print a paste-ready ChatGPT project instruction using session tools and every repository rule. Writes no files.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ChatGPT project instructions
|
|
7
|
+
|
|
8
|
+
Write no files. Ask: "What is the ChatGPT connector (plugin) name, and what tool prefix does it use? The default prefix is mcp_proxy."
|
|
9
|
+
|
|
10
|
+
Read root AGENTS.md using this session's read tool. If missing, omit Repository rules and report that it is missing. Use this session's tools and their schemas as the source for Tools, not a fixed product inventory. Generate one short line per tool or group with unprefixed names. Do not include product-specific content in the generated instruction.
|
|
11
|
+
|
|
12
|
+
Condense every AGENTS.md rule into Repository rules. Preserve commands, paths, package names, and exceptions word for word. Shorten wording only, never drop a rule. Replace placeholders below with the supplied connector and prefix, safely escaped as JavaScript string literals.
|
|
13
|
+
|
|
14
|
+
The entire output must be at most 8,000 characters, including fences, count, and notices. Count characters with a read-only session command such as printf '%s' ... | wc -m without writing a file. Without a shell, label the count estimated and use a conservative upper bound. Never accept an estimated count over the limit. Shorten tool lines first, then wording. If every rule still cannot fit, report the rules that do not fit instead of printing a block that drops rules. Do not print a block unless the strict maximum is satisfied.
|
|
15
|
+
|
|
16
|
+
Output exactly one four-backtick fenced block containing the completed template (its js fence is nested), followed by Character count: N (or an explicitly estimated upper bound). State outside the block that connector calls were not tested. Use no em-dashes.
|
|
17
|
+
|
|
18
|
+
## Template
|
|
19
|
+
|
|
20
|
+
# <PLUGIN> tools in code mode
|
|
21
|
+
|
|
22
|
+
Work runs on the session host repository. Do not use a local shell, Python, file tools, or local paths.
|
|
23
|
+
|
|
24
|
+
## Calling tools
|
|
25
|
+
|
|
26
|
+
Call tools from exec through the global tools object, never through tool search. ALL_TOOLS lists them all. Begin every exec with:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const P = '<PREFIX>_';
|
|
30
|
+
const T = Object.create(null);
|
|
31
|
+
for (const t of ALL_TOOLS) {
|
|
32
|
+
const i = t.name.lastIndexOf(P);
|
|
33
|
+
if (i < 0) continue;
|
|
34
|
+
const n = t.name.slice(i + P.length);
|
|
35
|
+
if (Object.hasOwn(T, n)) throw new Error(`duplicate ${n}: ${T[n]}, ${t.name}; select the connector namespace`);
|
|
36
|
+
T[n] = t.name;
|
|
37
|
+
}
|
|
38
|
+
const call = async (n, a = {}) => {
|
|
39
|
+
if (!T[n]) throw new Error(`no ${n}; have ${Object.keys(T)}`);
|
|
40
|
+
const r = await tools[T[n]](a);
|
|
41
|
+
text(JSON.stringify(r, null, 1));
|
|
42
|
+
return r;
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If duplicate matches occur across plugins, stop and select the confirmed plugin namespace using ALL_TOOLS metadata or exact fully qualified names before rebuilding T. Never silently select a duplicate short name. Calls always use exact ALL_TOOLS names.
|
|
47
|
+
|
|
48
|
+
In the first exec of a chat, print Object.keys(T), then call load_context. If T is empty, print the ALL_TOOLS names and stop. Await every call, print its result, and check isError. Codes are in structuredContent.code. Read arguments from the tool's ALL_TOOLS description and schema. Load skills with call('load_skill', { name }).
|
|
49
|
+
|
|
50
|
+
## When a call fails
|
|
51
|
+
|
|
52
|
+
- TOOL_CALL_FAILED and SESSION_RESULT_WITHHELD: inspect state before retrying.
|
|
53
|
+
- SESSION_BUSY: the call did not start. Retry once after the turn finishes.
|
|
54
|
+
- SESSION_TOOL_SURFACE_CHANGED: follow its message once.
|
|
55
|
+
- A name missing from T does not prove it is ungranted. Confirm once with session_capabilities, then tell the user. If that wrapper is missing too, report inability to confirm.
|
|
56
|
+
- load_extra_tools lists tools added or changed after your catalog loaded. Empty means nothing was added or changed, not that existing tools are missing. Run a returned tool through use_extra_tools with the exact returned name.
|
|
57
|
+
- "Skill is not granted or active": continue without it.
|
|
58
|
+
- Quote exact error messages. If the cause is unknown, say "cause not established".
|
|
59
|
+
|
|
60
|
+
## Tools
|
|
61
|
+
|
|
62
|
+
<One short line per session tool or group. ALL_TOOLS is authoritative; the session inventory can differ from this connection's grants.>
|
|
63
|
+
|
|
64
|
+
## Repository rules
|
|
65
|
+
|
|
66
|
+
<Every root AGENTS.md rule condensed, preserving exact commands, paths, package names, and exceptions>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: po-use-help
|
|
3
|
+
description: Set up and debug Po agents using installed package guidance and scoped, read-only diagnostics. Diagnose missing capabilities before proposing authorized repairs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Use Doom Pi Help
|
|
7
|
+
|
|
8
|
+
Use Help for agent setup, configuration, missing capabilities, and debugging the current session. Start from the user's expected behavior and an observed symptom. A skill describes a workflow; it does not grant the tools or permissions mentioned in it.
|
|
9
|
+
|
|
10
|
+
## Activate and inspect
|
|
11
|
+
|
|
12
|
+
Toggle Help through the minor-mode menu, `SPC h e`, `/minor help`, or `/doom-help`. The command toggles on both Pi and the web/server host. Activation adds Help-only guidance and diagnostics without replacing the ordinary tool set or changing other modes.
|
|
13
|
+
|
|
14
|
+
Call `help_status` to inspect the applied Help capabilities and their owners. A pending skill count means discovery has not completed or its consumer is unavailable, not that every registered descriptor is usable. Report degraded contributors separately and continue with healthy contributions. Missing, shadowed, restricted, and unavailable resources are different conditions.
|
|
15
|
+
|
|
16
|
+
Select the narrowest available guidance and load it only when needed. Do not paste every package manual into the conversation. Pi resolves package indexes against the installed version, an immutable cache, or an integrity-verified exact-version fallback. Server skills point to the installed package's published resources.
|
|
17
|
+
|
|
18
|
+
## Set up or repair an agent
|
|
19
|
+
|
|
20
|
+
Use `diagnose_setup` when contributed by the distribution. It checks saved configuration, installed packages, and sync drift for the bound workspace. Its result distinguishes those checks from the applied session selection. It does not test provider authentication, network health, or the quality of an agent run. Parser error text and configuration values are omitted to protect secrets.
|
|
21
|
+
|
|
22
|
+
Follow the indicated configuration, profile, major-mode, or domain skill. Read both the personal and repository configuration through authorized tools before proposing changes. Explain source precedence and preserve unrelated settings. A saved change may require a separate authorized reload or selection transition before it affects the session.
|
|
23
|
+
|
|
24
|
+
When creating or changing hooks, load `po-author-hook`, contributed by `@agimon-ai/po-hook`. It covers `.po/hooks.yaml`, group selection, compiled TypeScript modules, command hooks, child behavior, and the sync-then-reload workflow. If it is absent, inspect the hook package's activation and resource availability rather than inventing a hook API.
|
|
25
|
+
|
|
26
|
+
Configuration edits, package installation, model changes, authentication, permissions, and restarts require the existing approval and execution mechanisms. Present the intended change and verification first. Do not enable a domain, plugin, MCP server, shell, or network permission merely because a diagnostic would be easier with it.
|
|
27
|
+
|
|
28
|
+
## Debug an agent or a missing capability
|
|
29
|
+
|
|
30
|
+
Use `diagnose_agent` when the log package contributes it, then read `po-debug-agent` for interpretation and deeper investigation. Begin with the current-session one-day window. Empty or unavailable telemetry is not evidence of a healthy run. Token sample coverage is not event-capture completeness.
|
|
31
|
+
|
|
32
|
+
For a missing tool or skill, inspect its owner, selected domains and modes, discovery status, collisions, and restrictions. Use the available package guidance for MCP, skills, runners, and other features. If the relevant capability is absent, report what is missing and what an operator must check. Do not invent its cause or claim a command ran because its source exists.
|
|
33
|
+
|
|
34
|
+
Separate observed evidence from hypotheses. After an authorized repair, reproduce the original symptom, inspect the resulting capability or diagnostic state, and report the verified outcome and remaining limitations.
|
|
35
|
+
|
|
36
|
+
## Leave Help
|
|
37
|
+
|
|
38
|
+
Deactivate when support guidance is no longer needed. Help-only skills and tools are withdrawn from future discovery and calls. Ordinary capabilities remain subject to their existing restrictions. Cancellation stops supported in-flight Help work but cannot undo completed effects. Previously read guidance and results can remain in conversation history, and cached package files can remain on disk.
|
|
39
|
+
|
|
40
|
+
Help is a local agent capability. Its activation does not expose these diagnostics to remote MCP clients or widen a remote client's grant.
|