pullfrog 0.1.10 → 0.1.12
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/dist/agents/shared.d.ts +2 -0
- package/dist/cli.mjs +558 -252
- package/dist/external.d.ts +1 -1
- package/dist/index.js +557 -251
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal.js +57 -2
- package/dist/mcp/checkout.d.ts +1 -1
- package/dist/models.d.ts +21 -8
- package/dist/toolState.d.ts +7 -0
- package/dist/utils/byokFallback.d.ts +2 -3
- package/dist/utils/codexHome.d.ts +0 -8
- package/dist/utils/runLifecycle.d.ts +7 -4
- package/dist/utils/setup.d.ts +44 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/package.json +1 -1
package/dist/internal/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Re-exports shared types, values, and utilities needed by the Next.js app.
|
|
4
4
|
*/
|
|
5
5
|
export type { AuthorPermission, ModelAlias, ModelProvider, Payload, PayloadEvent, ProviderConfig, PushPermission, ShellPermission, ToolPermission, WriteablePayload, } from "../external.ts";
|
|
6
|
-
export { getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, modelAliases, parseModel, providers, pullfrogMcpName, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
|
|
6
|
+
export { DEFAULT_PROXY_MODEL, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, modelAliases, parseModel, providers, pullfrogMcpName, resolveCliModel, resolveDisplayAlias, resolveModelSlug, resolveOpenRouterModel, } from "../external.ts";
|
|
7
7
|
export type { Mode } from "../modes.ts";
|
|
8
8
|
export { modes } from "../modes.ts";
|
|
9
9
|
export type { BuildPullfrogFooterParams, WorkflowRunFooterInfo, } from "../utils/buildPullfrogFooter.ts";
|
package/dist/internal.js
CHANGED
|
@@ -257,6 +257,11 @@ var providers = {
|
|
|
257
257
|
resolve: "opencode/kimi-k2.6",
|
|
258
258
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
259
259
|
},
|
|
260
|
+
"minimax-m2.5": {
|
|
261
|
+
displayName: "MiniMax M2.5",
|
|
262
|
+
resolve: "opencode/minimax-m2.5",
|
|
263
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
264
|
+
},
|
|
260
265
|
"gpt-5-nano": {
|
|
261
266
|
displayName: "GPT Nano",
|
|
262
267
|
resolve: "opencode/gpt-5-nano",
|
|
@@ -273,7 +278,9 @@ var providers = {
|
|
|
273
278
|
displayName: "MiniMax M2.5",
|
|
274
279
|
resolve: "opencode/minimax-m2.5-free",
|
|
275
280
|
envVars: [],
|
|
276
|
-
isFree: true
|
|
281
|
+
isFree: true,
|
|
282
|
+
fallback: "opencode/big-pickle",
|
|
283
|
+
hidden: true
|
|
277
284
|
}
|
|
278
285
|
}
|
|
279
286
|
}),
|
|
@@ -291,6 +298,25 @@ var providers = {
|
|
|
291
298
|
}
|
|
292
299
|
}
|
|
293
300
|
}),
|
|
301
|
+
vertex: provider({
|
|
302
|
+
displayName: "Google Vertex AI",
|
|
303
|
+
envVars: [
|
|
304
|
+
"VERTEX_SERVICE_ACCOUNT_JSON",
|
|
305
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
306
|
+
"VERTEX_LOCATION",
|
|
307
|
+
"VERTEX_MODEL_ID"
|
|
308
|
+
],
|
|
309
|
+
models: {
|
|
310
|
+
// single routing entry — the actual Vertex AI model ID is read from
|
|
311
|
+
// VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
|
|
312
|
+
// catalog individual Vertex models.
|
|
313
|
+
byok: {
|
|
314
|
+
displayName: "Google Vertex AI",
|
|
315
|
+
resolve: "vertex",
|
|
316
|
+
routing: "vertex"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}),
|
|
294
320
|
openrouter: provider({
|
|
295
321
|
displayName: "OpenRouter",
|
|
296
322
|
envVars: ["OPENROUTER_API_KEY"],
|
|
@@ -392,6 +418,11 @@ var providers = {
|
|
|
392
418
|
displayName: "Kimi K2",
|
|
393
419
|
resolve: "openrouter/moonshotai/kimi-k2.6",
|
|
394
420
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
421
|
+
},
|
|
422
|
+
"minimax-m2.5": {
|
|
423
|
+
displayName: "MiniMax M2.5",
|
|
424
|
+
resolve: "openrouter/minimax/minimax-m2.5",
|
|
425
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
395
426
|
}
|
|
396
427
|
}
|
|
397
428
|
})
|
|
@@ -445,6 +476,11 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
445
476
|
hidden: def.hidden ?? false
|
|
446
477
|
}))
|
|
447
478
|
);
|
|
479
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "moonshotai/kimi-k2");
|
|
480
|
+
if (!defaultProxyAlias?.openRouterResolve) {
|
|
481
|
+
throw new Error("DEFAULT_PROXY_MODEL: moonshotai/kimi-k2 missing openRouterResolve");
|
|
482
|
+
}
|
|
483
|
+
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
448
484
|
function resolveModelSlug(slug) {
|
|
449
485
|
return modelAliases.find((a) => a.slug === slug)?.resolve;
|
|
450
486
|
}
|
|
@@ -668,7 +704,25 @@ function computeModes(agentId) {
|
|
|
668
704
|
|
|
669
705
|
Otherwise delegate the \`${REVIEWER_AGENT_NAME}\` subagent to review your diff with fresh eyes against YOUR TASK. The subagent's baked-in system prompt enforces a non-mutative + non-recursive contract: read-only file/search/web tools and read-only MCP queries only; no writes, shell side effects, state-changing MCP calls, or nested subagent dispatch. Enforcement is prose-only \u2014 restate the constraint in your dispatch instructions and do not relax it.
|
|
670
706
|
|
|
671
|
-
|
|
707
|
+
Compose your \`${REVIEWER_AGENT_NAME}\` dispatch prompt using this template verbatim, substituting the \`<...>\` placeholders. The preamble aligns the orchestrator side of the dispatch contract with the reviewer's baked-in system prompt \u2014 both ends say the same thing about where the work lives and what to do on an empty diff.
|
|
708
|
+
|
|
709
|
+
\`\`\`
|
|
710
|
+
## What you're reviewing
|
|
711
|
+
This is a PRE-COMMIT Build-mode self-review. The work to review lives in the working tree (uncommitted), NOT in committed history.
|
|
712
|
+
|
|
713
|
+
Branch: <branch> (off <base>)
|
|
714
|
+
Canonical diff command: git diff origin/<base>
|
|
715
|
+
|
|
716
|
+
If that command returns empty, treat it as "no changes \u2014 nothing to review" and stop per your system prompt. Do not search for the work elsewhere.
|
|
717
|
+
|
|
718
|
+
## Your task
|
|
719
|
+
<YOUR TASK content>
|
|
720
|
+
|
|
721
|
+
## Build-phase failures
|
|
722
|
+
<tight summary \u2014 what broke, root cause, the fix \u2014 or "no build-phase failures">
|
|
723
|
+
\`\`\`
|
|
724
|
+
|
|
725
|
+
Follow the template with the diff content (\`git diff origin/<base-branch>\`, single-rev form \u2014 \`main...HEAD\` and \`--cached\` both miss the uncommitted edits self-review runs on) and your task brief. Instruct the subagent to flag bugs, logic errors, missing edge cases, gaps between request and diff, and unintended changes.
|
|
672
726
|
|
|
673
727
|
Delegation + research discipline (distilled from \`/anneal\` canonical \u2014 these are codified learnings from many review rounds, not theoretical best practices):
|
|
674
728
|
- Do NOT summarize what you implemented \u2014 that biases the subagent toward validating the shape of your solution rather than questioning it.
|
|
@@ -1235,6 +1289,7 @@ function isValidTimeString(input) {
|
|
|
1235
1289
|
return parseTimeString(input) !== null;
|
|
1236
1290
|
}
|
|
1237
1291
|
export {
|
|
1292
|
+
DEFAULT_PROXY_MODEL,
|
|
1238
1293
|
LEAPING_INTO_ACTION_PREFIX,
|
|
1239
1294
|
MAX_LEARNINGS_LENGTH,
|
|
1240
1295
|
PULLFROG_DIVIDER,
|
package/dist/mcp/checkout.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export type CheckoutPrResult = {
|
|
|
48
48
|
* this is the core diff formatting logic, extracted for testability.
|
|
49
49
|
*/
|
|
50
50
|
export declare function fetchAndFormatPrDiff(ctx: ToolContext, pullNumber: number): Promise<FetchAndFormatPrDiffResult>;
|
|
51
|
-
import type
|
|
51
|
+
import { type GitContext } from "../utils/setup.ts";
|
|
52
52
|
export type PrData = {
|
|
53
53
|
number: number;
|
|
54
54
|
headSha: string;
|
package/dist/models.d.ts
CHANGED
|
@@ -10,15 +10,17 @@
|
|
|
10
10
|
*
|
|
11
11
|
* `"bedrock"` means the actual model ID comes from `BEDROCK_MODEL_ID`
|
|
12
12
|
* (an AWS-canonical Bedrock model ID like `us.anthropic.claude-opus-4-7`
|
|
13
|
-
* or `amazon.nova-pro-v1:0`).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
13
|
+
* or `amazon.nova-pro-v1:0`). `"vertex"` means the actual model ID comes
|
|
14
|
+
* from `VERTEX_MODEL_ID` (a Vertex AI model ID like
|
|
15
|
+
* `claude-opus-4-1@20250805` or `gemini-2.5-pro`). enterprise hosted-model
|
|
16
|
+
* customers self-select for version control — silent alias bumps would break
|
|
17
|
+
* compliance review, model-access enrollment, and provisioned-throughput
|
|
18
|
+
* contracts. so the single `bedrock/byok` and `vertex/byok` entries are
|
|
19
|
+
* routing slugs, not model aliases: the harness reads the backend-specific
|
|
20
|
+
* env var and routes to claude-code for Anthropic IDs or opencode for
|
|
21
|
+
* everything else.
|
|
20
22
|
*/
|
|
21
|
-
export type ModelRouting = "bedrock";
|
|
23
|
+
export type ModelRouting = "bedrock" | "vertex";
|
|
22
24
|
export interface ModelAlias {
|
|
23
25
|
/** stable alias stored in DB, e.g. "anthropic/claude-opus" */
|
|
24
26
|
slug: string;
|
|
@@ -84,6 +86,7 @@ export declare const providers: {
|
|
|
84
86
|
moonshotai: ProviderConfig;
|
|
85
87
|
opencode: ProviderConfig;
|
|
86
88
|
bedrock: ProviderConfig;
|
|
89
|
+
vertex: ProviderConfig;
|
|
87
90
|
openrouter: ProviderConfig;
|
|
88
91
|
};
|
|
89
92
|
export type ModelProvider = keyof typeof providers;
|
|
@@ -100,6 +103,7 @@ export declare function getModelEnvVars(slug: string): string[];
|
|
|
100
103
|
* see `provider.managedCredentials` and wiki/codex-auth.md. */
|
|
101
104
|
export declare function getModelManagedCredentials(slug: string): string[];
|
|
102
105
|
export declare const modelAliases: ModelAlias[];
|
|
106
|
+
export declare const DEFAULT_PROXY_MODEL: string;
|
|
103
107
|
/** resolve a model slug to its concrete models.dev specifier (e.g. "anthropic/claude-opus-4-6") */
|
|
104
108
|
export declare function resolveModelSlug(slug: string): string | undefined;
|
|
105
109
|
/**
|
|
@@ -127,6 +131,8 @@ export declare function resolveCliModel(slug: string): string | undefined;
|
|
|
127
131
|
export declare function resolveOpenRouterModel(slug: string): string | undefined;
|
|
128
132
|
/** env var that supplies the Bedrock model ID for the `bedrock/byok` slug. */
|
|
129
133
|
export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
134
|
+
/** env var that supplies the Vertex AI model ID for the `vertex/byok` slug. */
|
|
135
|
+
export declare const VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
|
|
130
136
|
/**
|
|
131
137
|
* the Bedrock model ID passed to claude-code or opencode is whatever the
|
|
132
138
|
* user set in `BEDROCK_MODEL_ID` — Pullfrog never resolves or upgrades it.
|
|
@@ -153,4 +159,11 @@ export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
|
153
159
|
* include the foundation segment in the profile name.
|
|
154
160
|
*/
|
|
155
161
|
export declare function isBedrockAnthropicId(bedrockModelId: string): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Vertex Anthropic model IDs start with the Claude family name, e.g.
|
|
164
|
+
* `claude-opus-4-1@20250805`. partner-model resource paths can contain the
|
|
165
|
+
* substring "anthropic" elsewhere, so the Bedrock segment check does not
|
|
166
|
+
* transfer — anchor on the model ID prefix instead.
|
|
167
|
+
*/
|
|
168
|
+
export declare function isVertexAnthropicId(vertexModelId: string): boolean;
|
|
156
169
|
export {};
|
package/dist/toolState.d.ts
CHANGED
|
@@ -57,6 +57,13 @@ export type CommentableLines = {
|
|
|
57
57
|
export interface ToolState {
|
|
58
58
|
pushUrl?: string;
|
|
59
59
|
pushDest?: StoredPushDest;
|
|
60
|
+
initialHead?: {
|
|
61
|
+
kind: "branch";
|
|
62
|
+
name: string;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "detached";
|
|
65
|
+
sha: string;
|
|
66
|
+
};
|
|
60
67
|
issueNumber?: number;
|
|
61
68
|
checkoutSha?: string;
|
|
62
69
|
commentableLinesByFile?: Map<string, CommentableLines>;
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
* Slug we fall back to when a BYOK-required model is configured but the
|
|
3
3
|
* runner has no provider key in env. Picked because it's free
|
|
4
4
|
* (`isFree: true`, `envVars: []` — see `action/models.ts`), stable, and
|
|
5
|
-
* currently
|
|
6
|
-
* smarter free model is added later, update this single constant.
|
|
5
|
+
* currently served by OpenCode Zen without a key.
|
|
7
6
|
*
|
|
8
7
|
* The slug is intentionally hard-coded and not a config knob — the
|
|
9
8
|
* fallback is a safety net, not a user-facing preference, and adding a
|
|
10
9
|
* config surface here would just push the same "what to fall back to"
|
|
11
10
|
* decision into another setting that goes stale the same way.
|
|
12
11
|
*/
|
|
13
|
-
export declare const FREE_FALLBACK_SLUG = "opencode/
|
|
12
|
+
export declare const FREE_FALLBACK_SLUG = "opencode/big-pickle";
|
|
14
13
|
export type FallbackDecision = {
|
|
15
14
|
fallback: false;
|
|
16
15
|
} | {
|
|
@@ -13,11 +13,3 @@ export interface InstalledCodexAuth {
|
|
|
13
13
|
* returns null when the env var is absent, malformed, or wrong auth mode —
|
|
14
14
|
* caller treats null as "no codex auth, fall through to API key flow". */
|
|
15
15
|
export declare function installCodexAuth(): InstalledCodexAuth | null;
|
|
16
|
-
/** convert an on-disk OpenCode auth.json back to the Codex CLI shape so the
|
|
17
|
-
* post-hook can write it to the Pullfrog secret store. returns null when the
|
|
18
|
-
* file's `openai` entry is missing, has the wrong type, or hasn't actually
|
|
19
|
-
* refreshed (refresh token unchanged from `originalRefresh`). */
|
|
20
|
-
export declare function detectCodexRefresh(params: {
|
|
21
|
-
authFileContent: string;
|
|
22
|
-
originalRefresh: string;
|
|
23
|
-
}): string | null;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import type { AgentResult } from "../agents/shared.ts";
|
|
25
25
|
import type { ToolContext } from "../mcp/server.ts";
|
|
26
26
|
import type { ToolState } from "../toolState.ts";
|
|
27
|
-
import type
|
|
27
|
+
import { type RenderedRunError } from "./runErrorRenderer.ts";
|
|
28
28
|
/**
|
|
29
29
|
* Best-effort cleanup shared by both run-end paths:
|
|
30
30
|
* 1. post-review cleanup (dispatch follow-up re-review on submitted reviews)
|
|
@@ -40,9 +40,12 @@ export declare function persistRunArtifacts(toolContext: ToolContext): Promise<v
|
|
|
40
40
|
*
|
|
41
41
|
* 1. shared best-effort cleanup via `persistRunArtifacts`
|
|
42
42
|
* 2. when the harness returned `success=false` (e.g. unsubmitted-review
|
|
43
|
-
* gate exhausted retries, stop-hook persistently failing),
|
|
44
|
-
* the error in the progress comment
|
|
45
|
-
*
|
|
43
|
+
* gate exhausted retries, stop-hook persistently failing), render via
|
|
44
|
+
* `renderRunError` and surface the error in BOTH the progress comment
|
|
45
|
+
* (rendered.comment) and the Actions job summary (rendered.summary,
|
|
46
|
+
* prepended below in step 4) — same classifier as the catch path so
|
|
47
|
+
* the user sees it instead of a deleted-comment void / empty summary
|
|
48
|
+
* tab
|
|
46
49
|
* 3. when the run succeeded and the progress comment was never finalized
|
|
47
50
|
* via `report_progress`, delete it (three sub-cases — orphan
|
|
48
51
|
* "Leaping into action" comment, abandoned checklist, agent wrote
|
package/dist/utils/setup.d.ts
CHANGED
|
@@ -8,6 +8,32 @@ export interface SetupOptions {
|
|
|
8
8
|
* Create a shared temp directory for the action
|
|
9
9
|
*/
|
|
10
10
|
export declare function createTempDirectory(): string;
|
|
11
|
+
/**
|
|
12
|
+
* snapshot-and-delete the GHA runner's known credential leak surfaces inside
|
|
13
|
+
* `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
|
|
14
|
+
* can grep:
|
|
15
|
+
* - `_runner_file_commands/set_output_*` for `core.setOutput('token', ghs_…)`
|
|
16
|
+
* calls made by earlier composite-action steps (e.g.
|
|
17
|
+
* pullfrog/pullfrog/get-installation-token);
|
|
18
|
+
* - `<uuid>.sh` rendered step scripts whose `run: |` body embeds
|
|
19
|
+
* `${{ steps.token.outputs.token }}` literally (GHA expands BEFORE writing);
|
|
20
|
+
* - `git-credentials-*.config` written by `actions/checkout@v6` for the
|
|
21
|
+
* workflow GITHUB_TOKEN.
|
|
22
|
+
*
|
|
23
|
+
* the running bash process already has its own `.sh` open via fd, so the
|
|
24
|
+
* unlink is safe — `unlink` removes the dirent, the kernel keeps reading.
|
|
25
|
+
*
|
|
26
|
+
* preserves every `_runner_file_commands/` file path the runner pre-allocated
|
|
27
|
+
* for OUR step — `$GITHUB_OUTPUT`, `$GITHUB_ENV`, `$GITHUB_PATH`,
|
|
28
|
+
* `$GITHUB_STATE`, `$GITHUB_STEP_SUMMARY`. those are read by the runner
|
|
29
|
+
* AFTER we exit (or by our own `post:` hook), and wiping them would break
|
|
30
|
+
* pullfrog's `result` output, `post:` state handoff, and job summary.
|
|
31
|
+
*
|
|
32
|
+
* silent no-op when `$RUNNER_TEMP` is unset (local dev, `pnpm play`).
|
|
33
|
+
* per-file errors are tolerated — the runner may delete files between
|
|
34
|
+
* our readdir and our unlink.
|
|
35
|
+
*/
|
|
36
|
+
export declare function wipeRunnerLeakSurface(): void;
|
|
11
37
|
/**
|
|
12
38
|
* Setup the test repository for running actions
|
|
13
39
|
*/
|
|
@@ -44,3 +70,21 @@ export type SetupGitParams = GitContext;
|
|
|
44
70
|
* it is assumed to be potentially exfiltratable, so it has limited scope.
|
|
45
71
|
*/
|
|
46
72
|
export declare function setupGit(params: SetupGitParams): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* snapshot the current HEAD as either a branch name (when on a named branch)
|
|
75
|
+
* or a literal SHA (when detached). used by setupGit to pin the run-entry
|
|
76
|
+
* position and by checkout_pr to compare the live HEAD against it.
|
|
77
|
+
*
|
|
78
|
+
* splitting the two cases is load-bearing: `git rev-parse --abbrev-ref HEAD`
|
|
79
|
+
* returns the sentinel string `"HEAD"` on detached entry — which is the
|
|
80
|
+
* default `actions/checkout` state for `pull_request` events. storing that
|
|
81
|
+
* raw string would make any future detached state (including a subagent's
|
|
82
|
+
* `git checkout --detach <sha>`) compare equal.
|
|
83
|
+
*/
|
|
84
|
+
export declare function captureInitialHead(repoDir: string): {
|
|
85
|
+
kind: "branch";
|
|
86
|
+
name: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: "detached";
|
|
89
|
+
sha: string;
|
|
90
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
|
|
2
|
+
export declare const GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
|
|
3
|
+
export declare const GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
|
|
4
|
+
export declare const VERTEX_LOCATION_ENV = "VERTEX_LOCATION";
|
|
5
|
+
export type VertexCredentials = {
|
|
6
|
+
credentialsPath: string;
|
|
7
|
+
secretDir: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function isVertexRoute(model: string | undefined): boolean;
|
|
10
|
+
export declare function readProjectIdFromVertexServiceAccountJson(): string | undefined;
|
|
11
|
+
export declare function materializeVertexCredentials(params: {
|
|
12
|
+
model: string | undefined;
|
|
13
|
+
}): VertexCredentials | undefined;
|
|
14
|
+
export declare function cleanupVertexCredentials(credentials: VertexCredentials | undefined): void;
|
|
15
|
+
export declare function applyClaudeVertexEnv(env: Record<string, string | undefined>): void;
|
|
16
|
+
export declare function resolveVertexOpenCodeModel(model: string | undefined): string | undefined;
|