@inhuman.tools/env-capability-module-prompt 0.0.0-stage → 0.2.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.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Merkle Bonsai
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * One rendered `.prompt` call, and the host port for an isolated completion.
3
+ * A ProgrammaticJob parents an omitted-spec AgentCallJob instead of calling the port.
4
+ */
5
+ import type { ReasoningEffort } from "@inhuman.tools/env-capability-dotprompt";
6
+ import type { CompletionExpectation, PromptMessageRole } from "@inhuman.tools/harness-model";
7
+ /** Session/research intern port. Homed `round` is mutated in place. `responseSchemaJson` is the serialized schema, matching CompleteFields. */
8
+ export type PromptCompleteRequest = {
9
+ readonly connectionId: string;
10
+ readonly model: string;
11
+ readonly promptText?: string;
12
+ readonly responseSchemaJson?: string;
13
+ readonly signal?: AbortSignal;
14
+ readonly round: CompletionExpectation;
15
+ };
16
+ export type PromptComplete = (req: PromptCompleteRequest) => Promise<{
17
+ readonly text: string;
18
+ readonly thought?: string;
19
+ readonly thoughtKind?: string;
20
+ }>;
21
+ export declare class RenderedPrompt {
22
+ readonly model: string | null;
23
+ readonly reasoningEffort: ReasoningEffort | null;
24
+ readonly responseSchema: Record<string, unknown> | null;
25
+ readonly faceName: string;
26
+ /** Null inherits the caller catalog; an empty list is an explicit empty overlay. */
27
+ readonly tools: readonly string[] | null;
28
+ readonly messages: readonly [PromptMessageRole, string][];
29
+ constructor(model: string | null, reasoningEffort: ReasoningEffort | null, responseSchema: Record<string, unknown> | null, faceName: string,
30
+ /** Null inherits the caller catalog; an empty list is an explicit empty overlay. */
31
+ tools: readonly string[] | null, messages: readonly [PromptMessageRole, string][]);
32
+ }
33
+ //# sourceMappingURL=bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAE7F,+IAA+I;AAC/I,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,qBAAqB,KACvB,OAAO,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElG,qBAAa,cAAc;aAEP,KAAK,EAAE,MAAM,GAAG,IAAI;aACpB,eAAe,EAAE,eAAe,GAAG,IAAI;aACvC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;aAC9C,QAAQ,EAAE,MAAM;IAChC,oFAAoF;aACpE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;aAC/B,QAAQ,EAAE,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,EAAE;gBANhD,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,eAAe,EAAE,eAAe,GAAG,IAAI,EACvC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAC9C,QAAQ,EAAE,MAAM;IAChC,oFAAoF;IACpE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EAC/B,QAAQ,EAAE,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,EAAE;CAEnE"}
package/dist/bundle.js ADDED
@@ -0,0 +1,19 @@
1
+ export class RenderedPrompt {
2
+ model;
3
+ reasoningEffort;
4
+ responseSchema;
5
+ faceName;
6
+ tools;
7
+ messages;
8
+ constructor(model, reasoningEffort, responseSchema, faceName,
9
+ /** Null inherits the caller catalog; an empty list is an explicit empty overlay. */
10
+ tools, messages) {
11
+ this.model = model;
12
+ this.reasoningEffort = reasoningEffort;
13
+ this.responseSchema = responseSchema;
14
+ this.faceName = faceName;
15
+ this.tools = tools;
16
+ this.messages = messages;
17
+ }
18
+ }
19
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAqBA,MAAM,OAAO,cAAc;IAEP;IACA;IACA;IACA;IAEA;IACA;IAPlB,YACkB,KAAoB,EACpB,eAAuC,EACvC,cAA8C,EAC9C,QAAgB;IAChC,oFAAoF;IACpE,KAA+B,EAC/B,QAAgD;QANhD,UAAK,GAAL,KAAK,CAAe;QACpB,oBAAe,GAAf,eAAe,CAAwB;QACvC,mBAAc,GAAd,cAAc,CAAgC;QAC9C,aAAQ,GAAR,QAAQ,CAAQ;QAEhB,UAAK,GAAL,KAAK,CAA0B;QAC/B,aAAQ,GAAR,QAAQ,CAAwC;IAC/D,CAAC;CACL"}
@@ -0,0 +1,6 @@
1
+ import { type ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
2
+ import { RenderedPrompt } from "./bundle.js";
3
+ export declare function renderPrompt(spec: ParsedPrompt, args: readonly unknown[]): RenderedPrompt;
4
+ /** Both prompt hosts install this prelude. Require parses once and closes over the spec. */
5
+ export declare const promptPrelude = "(define (ext/prompt/resolve contents)\n (let ((spec (dotprompt/parse (if (bytevector? contents) (utf8->string contents) contents)\n \"anonymous.prompt\")))\n ;; apply would run dotprompt/run under the lists capability's context.\n (lambda args\n (dotprompt/run spec args))))\n(require/register-extension \".prompt\" ext/prompt/resolve)";
6
+ //# sourceMappingURL=dotprompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotprompt.d.ts","sourceRoot":"","sources":["../src/dotprompt.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,YAAY,EAAyB,MAAM,yCAAyC,CAAC;AAKlH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAO7C,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,cAAc,CAoDzF;AAED,4FAA4F;AAC5F,eAAO,MAAM,aAAa,8XAMgC,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Render both prompt hosts call, and the prelude they install.
3
+ * `dotprompt/parse` is `dotpromptCapability`.
4
+ */
5
+ import { toJS } from "@here.build/arrival";
6
+ import { compileTemplate, runCompiledTemplate } from "@here.build/arrival-modules/handlebars";
7
+ import { isPlainRecord, reasoningEffortSchema } from "@inhuman.tools/env-capability-dotprompt";
8
+ import invariant from "tiny-invariant";
9
+ import { z } from "zod";
10
+ import { RenderedPrompt } from "./bundle.js";
11
+ const promptMeta = z.object({
12
+ model: z.string().optional(),
13
+ reasoningEffort: reasoningEffortSchema.optional(),
14
+ });
15
+ export function renderPrompt(spec, args) {
16
+ let pairs = args;
17
+ let positional;
18
+ if (pairs.length > 0) {
19
+ const head = String(pairs[0]);
20
+ if (!(head.startsWith(":") || head.startsWith("':"))) {
21
+ positional = pairs[0];
22
+ pairs = pairs.slice(1);
23
+ }
24
+ }
25
+ const folded = {};
26
+ if (pairs.length > 0) {
27
+ invariant(pairs.length % 2 === 0, "kwargs: needs an even number of trailing args (alternating :key value pairs)");
28
+ for (let i = 0; i < pairs.length; i += 2) {
29
+ folded[String(pairs[i]).replace(/^'?:/, "")] = toJS(pairs[i + 1]);
30
+ }
31
+ }
32
+ let inputs;
33
+ let meta;
34
+ if (positional !== undefined) {
35
+ const value = toJS(positional);
36
+ if (isPlainRecord(value) && Object.keys(folded).length === 0) {
37
+ const metaRaw = isPlainRecord(value.meta) ? value.meta : {};
38
+ const { meta: _meta, key: _key, ...rest } = value;
39
+ inputs = rest;
40
+ meta = promptMeta.parse(metaRaw);
41
+ }
42
+ else if (folded.evidence === undefined) {
43
+ folded.evidence = value;
44
+ }
45
+ }
46
+ if (inputs === undefined || meta === undefined) {
47
+ const metaRaw = isPlainRecord(folded.meta) ? folded.meta : {};
48
+ const { meta: _metaSlot, key: _keySlot, ...rest } = folded;
49
+ inputs = rest;
50
+ meta = promptMeta.parse(metaRaw);
51
+ }
52
+ const rendered = spec.sections.map((section) => [
53
+ section.role,
54
+ runCompiledTemplate(compileTemplate(section.source), [inputs]),
55
+ ]);
56
+ const model = [meta.model, spec.model].find((candidate) => typeof candidate === "string" && candidate !== "") ?? null;
57
+ return new RenderedPrompt(model, meta.reasoningEffort ?? spec.reasoningEffort, spec.responseSchema, spec.faceName, spec.tools, spec.mode === "instruct" ? [["user", rendered.map(([, content]) => content).join("\n\n")]] : rendered);
58
+ }
59
+ /** Both prompt hosts install this prelude. Require parses once and closes over the spec. */
60
+ export const promptPrelude = `(define (ext/prompt/resolve contents)
61
+ (let ((spec (dotprompt/parse (if (bytevector? contents) (utf8->string contents) contents)
62
+ "anonymous.prompt")))
63
+ ;; apply would run dotprompt/run under the lists capability's context.
64
+ (lambda args
65
+ (dotprompt/run spec args))))
66
+ (require/register-extension ".prompt" ext/prompt/resolve)`;
67
+ //# sourceMappingURL=dotprompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotprompt.js","sourceRoot":"","sources":["../src/dotprompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { type PromptComplete, RenderedPrompt } from "./bundle.js";
2
+ export { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
3
+ export { promptIsolatedCapability } from "./run-isolated.js";
4
+ export { promptProgramCapability } from "./run-program.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { RenderedPrompt } from "./bundle.js";
2
+ export { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
3
+ export { promptIsolatedCapability } from "./run-isolated.js";
4
+ export { promptProgramCapability } from "./run-program.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Isolated host for `.prompt`. `dotprompt/run` performs one completion
3
+ * on the configured job (compact, classifier).
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { Job } from "@inhuman.tools/plexus-expectations";
7
+ import { z } from "zod";
8
+ export declare const promptIsolatedCapability: EnvCapability<{
9
+ job: z.ZodCustom<Job<unknown, unknown>, Job<unknown, unknown>>;
10
+ connectionId: z.ZodString;
11
+ model: z.ZodOptional<z.ZodString>;
12
+ /** Session/judge model. `model` is reserved by some exec hosts. */
13
+ completionModel: z.ZodOptional<z.ZodString>;
14
+ }, Record<string, never>>;
15
+ //# sourceMappingURL=run-isolated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-isolated.d.ts","sourceRoot":"","sources":["../src/run-isolated.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,EAAE,GAAG,EAAE,MAAM,oCAAoC,CAAC;AAEzD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,wBAAwB;;;;IAUjC,mEAAmE;;yBAqCrE,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Isolated host for `.prompt`. `dotprompt/run` performs one completion
3
+ * on the configured job (compact, classifier).
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { arrivalLoaderCapability } from "@here.build/arrival-modules";
7
+ import { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
8
+ import { CompletionExpectation, CompletionJob, ProgrammaticJob, PromptMessage } from "@inhuman.tools/harness-model";
9
+ import { Job } from "@inhuman.tools/plexus-expectations";
10
+ import invariant from "tiny-invariant";
11
+ import { z } from "zod";
12
+ import { promptPrelude, renderPrompt } from "./dotprompt.js";
13
+ export const promptIsolatedCapability = EnvCapability.define("ext/prompt/isolated", {
14
+ deps: [dotpromptCapability, arrivalLoaderCapability],
15
+ configuration: {
16
+ job: z.instanceof(Job).refine((job) => !(job instanceof ProgrammaticJob), {
17
+ error: "dotprompt/run: a program uses promptProgramCapability",
18
+ }),
19
+ connectionId: z
20
+ .string({ error: "dotprompt/run: connectionId is required" })
21
+ .refine((value) => value !== "", { error: "dotprompt/run: connectionId is required" }),
22
+ model: z.string().optional(),
23
+ /** Session/judge model. `model` is reserved by some exec hosts. */
24
+ completionModel: z.string().optional(),
25
+ },
26
+ symbols: (symbol, sz) => ({
27
+ "dotprompt/run": symbol.rosetta `dotprompt/run: completes the rendered prompt in isolation`({
28
+ input: [sz.box.pipe(z.instanceof(ParsedPrompt)), sz.list(sz.dynamic)],
29
+ output: [sz.dynamic],
30
+ provenance: "source",
31
+ requiresConfig: ["job"],
32
+ }, async function (spec, args) {
33
+ const bundle = renderPrompt(spec, args);
34
+ // Render overlays :meta, then the file model. The host model is appended here.
35
+ const model = [bundle.model, this.configuration.completionModel, this.configuration.model].find((candidate) => typeof candidate === "string" && candidate !== "") ?? null;
36
+ invariant(model != null, "dotprompt/run: model is required");
37
+ // The session orchestrator drives the CompletionJob. Await reads its result.
38
+ return await this.configuration.job.registerJob(new CompletionJob({
39
+ expectation: new CompletionExpectation({
40
+ connectionId: this.configuration.connectionId,
41
+ model,
42
+ responseSchema: bundle.responseSchema,
43
+ completionMode: "isolated",
44
+ promptMessages: bundle.messages.map(([role, content]) => new PromptMessage({ role, content })),
45
+ reasoningEffort: bundle.reasoningEffort,
46
+ }),
47
+ turnTail: this.configuration.job,
48
+ }));
49
+ }),
50
+ }),
51
+ prelude: promptPrelude,
52
+ });
53
+ //# sourceMappingURL=run-isolated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-isolated.js","sourceRoot":"","sources":["../src/run-isolated.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Program host for `.prompt`. `dotprompt/run` parents an omitted-spec
3
+ * AgentCallJob on the ProgrammaticJob and waits for the worker.
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { ProgrammaticJob } from "@inhuman.tools/harness-model";
7
+ import { z } from "zod";
8
+ export declare const promptProgramCapability: EnvCapability<{
9
+ job: z.ZodCustom<ProgrammaticJob, ProgrammaticJob>;
10
+ readonly: z.ZodDefault<z.ZodBoolean>;
11
+ }, Record<string, never>>;
12
+ //# sourceMappingURL=run-program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-program.d.ts","sourceRoot":"","sources":["../src/run-program.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAML,eAAe,EAGhB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,uBAAuB;;;yBAsDlC,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Program host for `.prompt`. `dotprompt/run` parents an omitted-spec
3
+ * AgentCallJob on the ProgrammaticJob and waits for the worker.
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { arrivalLoaderCapability } from "@here.build/arrival-modules";
7
+ import { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
8
+ import { AgentCallJob, claimCrossing, crossingPending, crossingWindow, isReplaying, ProgrammaticJob, PromptMessage, takeCrossing, } from "@inhuman.tools/harness-model";
9
+ import { runInAction, when } from "mobx";
10
+ import { z } from "zod";
11
+ import { promptPrelude, renderPrompt } from "./dotprompt.js";
12
+ const AGENT_ASK = "agent__ask";
13
+ export const promptProgramCapability = EnvCapability.define("ext/prompt/program", {
14
+ deps: [dotpromptCapability, arrivalLoaderCapability],
15
+ configuration: {
16
+ job: z.instanceof(ProgrammaticJob),
17
+ readonly: z.boolean().default(false),
18
+ },
19
+ symbols: (symbol, sz) => ({
20
+ "dotprompt/run": symbol.rosetta `dotprompt/run: parents an omitted-spec AgentCallJob on the program and waits`({
21
+ input: [sz.box.pipe(z.instanceof(ParsedPrompt)), sz.list(sz.dynamic)],
22
+ output: [sz.dynamic],
23
+ provenance: "source",
24
+ requiresConfig: ["job"],
25
+ }, async function (spec, args) {
26
+ const bundle = renderPrompt(spec, args);
27
+ const job = this.configuration.job;
28
+ const emission = this.runCtx.emission;
29
+ const path = job.trackMatch && emission != null ? claimCrossing(emission, crossingWindow(this)) : "";
30
+ if (path !== "" && emission != null) {
31
+ let existing = takeCrossing(job, emission, path);
32
+ if (existing == null && isReplaying(emission)) {
33
+ if (!job.completed && !job.cancelled) {
34
+ const joined = when(() => job.completed || job.cancelled || crossingPending(job, emission, path));
35
+ try {
36
+ await joined;
37
+ }
38
+ finally {
39
+ joined.cancel();
40
+ }
41
+ }
42
+ existing = takeCrossing(job, emission, path);
43
+ if (existing == null)
44
+ throw new Error("replay: no recorded dotprompt/run");
45
+ }
46
+ if (existing != null)
47
+ return await existing;
48
+ }
49
+ const minted = new AgentCallJob({
50
+ toolCallId: `${job.toolCallId}:prompt:${job.children.length + 1}`,
51
+ name: AGENT_ASK,
52
+ argsJson: "{}",
53
+ voidLegal: false,
54
+ readonly: this.configuration.readonly === true,
55
+ responseSchema: bundle.responseSchema,
56
+ promptMessages: bundle.messages.map(([role, content]) => new PromptMessage({ role, content })),
57
+ faceName: bundle.faceName.trim(),
58
+ tools: bundle.tools ?? [],
59
+ inheritCallerTools: bundle.tools === null,
60
+ reasoningEffort: bundle.reasoningEffort,
61
+ });
62
+ if (path !== "")
63
+ runInAction(() => (minted.track = path));
64
+ return await job.registerJob(minted);
65
+ }),
66
+ }),
67
+ prelude: promptPrelude,
68
+ });
69
+ //# sourceMappingURL=run-program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-program.js","sourceRoot":"","sources":["../src/run-program.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,EACX,eAAe,EACf,aAAa,EACb,YAAY,GACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,SAAS,GAAG,YAAY,CAAC;AAE/B,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAC,MAAM,CAAC,oBAAoB,EAAE;IAChF,IAAI,EAAE,CAAC,mBAAmB,EAAE,uBAAuB,CAAC;IACpD,aAAa,EAAE;QACb,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,eAAe,CAAC;QAClC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KACrC;IACD,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACxB,eAAe,EAAE,MAAM,CAAC,OAAO,CAAA,8EAA8E,CAC3G;YACE,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC;YACpB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,CAAC,KAAK,CAAC;SACxB,EACD,KAAK,WAAW,IAAI,EAAE,IAAI;YACxB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACtC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,IAAI,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACrG,IAAI,IAAI,KAAK,EAAE,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;gBACpC,IAAI,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACjD,IAAI,QAAQ,IAAI,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC9C,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;wBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,IAAI,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;wBAClG,IAAI,CAAC;4BACH,MAAM,MAAM,CAAC;wBACf,CAAC;gCAAS,CAAC;4BACT,MAAM,CAAC,MAAM,EAAE,CAAC;wBAClB,CAAC;oBACH,CAAC;oBACD,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAC7C,IAAI,QAAQ,IAAI,IAAI;wBAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;gBAC7E,CAAC;gBACD,IAAI,QAAQ,IAAI,IAAI;oBAAE,OAAO,MAAM,QAAQ,CAAC;YAC9C,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;gBAC9B,UAAU,EAAE,GAAG,GAAG,CAAC,UAAU,WAAW,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;gBACjE,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,KAAK,IAAI;gBAC9C,cAAc,EAAE,MAAM,CAAC,cAAc;gBACrC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9F,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;gBAChC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;gBACzB,kBAAkB,EAAE,MAAM,CAAC,KAAK,KAAK,IAAI;gBACzC,eAAe,EAAE,MAAM,CAAC,eAAe;aACxC,CAAC,CAAC;YACH,IAAI,IAAI,KAAK,EAAE;gBAAE,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;YAC1D,OAAO,MAAM,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CACF;KACF,CAAC;IACF,OAAO,EAAE,aAAa;CACvB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,67 @@
1
1
  {
2
2
  "name": "@inhuman.tools/env-capability-module-prompt",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "Arrival ext/prompt: (require \"x.prompt\") pretreats to a scheme lambda; a ProgrammaticJob parents an omitted-spec agent ask.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src",
18
+ "!**/__tests__"
19
+ ],
20
+ "dependencies": {
21
+ "@here.build/arrival": "^0.10.2",
22
+ "@here.build/arrival-modules": "^0.10.0",
23
+ "handlebars": "^4.7.9",
24
+ "tiny-invariant": "^1.3.3",
25
+ "zod": "^4.4.3",
26
+ "@inhuman.tools/env-capability-dotprompt": "^0.2.0",
27
+ "@inhuman.tools/harness-model": "^0.2.0",
28
+ "@inhuman.tools/harness-commons": "^0.2.0",
29
+ "@inhuman.tools/plexus-expectations": "^0.2.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^24.0.0",
33
+ "dedent": "1.7.2",
34
+ "eslint": "9.39.2",
35
+ "mobx": "6.16.1",
36
+ "typescript": "6.0.2",
37
+ "vitest": "4.1.0",
38
+ "@-internal-/eslint-configs": "0.0.0"
39
+ },
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/here-build/inhuman-harness.git",
44
+ "directory": "packages/env-capability-module-prompt"
45
+ },
46
+ "peerDependencies": {
47
+ "mobx": "6.16.1"
48
+ },
49
+ "browserslist": [
50
+ "last 2 chrome versions",
51
+ "last 2 firefox versions",
52
+ "last 2 safari versions",
53
+ "ios_saf >= 16.4",
54
+ "node >= 22"
55
+ ],
56
+ "author": "Merkle Bonsai",
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsc -p tsconfig.build.json",
62
+ "lint": "eslint .",
63
+ "lint:fix": "eslint . --fix",
64
+ "test": "tsc -p tsconfig.json --noEmit && vitest run",
65
+ "typecheck": "tsc -p tsconfig.json --noEmit"
66
+ }
6
67
  }
package/src/bundle.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * One rendered `.prompt` call, and the host port for an isolated completion.
3
+ * A ProgrammaticJob parents an omitted-spec AgentCallJob instead of calling the port.
4
+ */
5
+ import type { ReasoningEffort } from "@inhuman.tools/env-capability-dotprompt";
6
+ import type { CompletionExpectation, PromptMessageRole } from "@inhuman.tools/harness-model";
7
+
8
+ /** Session/research intern port. Homed `round` is mutated in place. `responseSchemaJson` is the serialized schema, matching CompleteFields. */
9
+ export type PromptCompleteRequest = {
10
+ readonly connectionId: string;
11
+ readonly model: string;
12
+ readonly promptText?: string;
13
+ readonly responseSchemaJson?: string;
14
+ readonly signal?: AbortSignal;
15
+ readonly round: CompletionExpectation;
16
+ };
17
+
18
+ export type PromptComplete = (
19
+ req: PromptCompleteRequest,
20
+ ) => Promise<{ readonly text: string; readonly thought?: string; readonly thoughtKind?: string }>;
21
+
22
+ export class RenderedPrompt {
23
+ constructor(
24
+ public readonly model: string | null,
25
+ public readonly reasoningEffort: ReasoningEffort | null,
26
+ public readonly responseSchema: Record<string, unknown> | null,
27
+ public readonly faceName: string,
28
+ /** Null inherits the caller catalog; an empty list is an explicit empty overlay. */
29
+ public readonly tools: readonly string[] | null,
30
+ public readonly messages: readonly [PromptMessageRole, string][],
31
+ ) {}
32
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Render both prompt hosts call, and the prelude they install.
3
+ * `dotprompt/parse` is `dotpromptCapability`.
4
+ */
5
+ import { type SchemeValue, toJS } from "@here.build/arrival";
6
+ import { compileTemplate, runCompiledTemplate } from "@here.build/arrival-modules/handlebars";
7
+ import { isPlainRecord, type ParsedPrompt, reasoningEffortSchema } from "@inhuman.tools/env-capability-dotprompt";
8
+ import { type PromptMessageRole } from "@inhuman.tools/harness-model";
9
+ import invariant from "tiny-invariant";
10
+ import { z } from "zod";
11
+
12
+ import { RenderedPrompt } from "./bundle.js";
13
+
14
+ const promptMeta = z.object({
15
+ model: z.string().optional(),
16
+ reasoningEffort: reasoningEffortSchema.optional(),
17
+ });
18
+
19
+ export function renderPrompt(spec: ParsedPrompt, args: readonly unknown[]): RenderedPrompt {
20
+ let pairs = args;
21
+ let positional: unknown;
22
+ if (pairs.length > 0) {
23
+ const head = String(pairs[0]);
24
+ if (!(head.startsWith(":") || head.startsWith("':"))) {
25
+ positional = pairs[0];
26
+ pairs = pairs.slice(1);
27
+ }
28
+ }
29
+ const folded: Record<string, unknown> = {};
30
+ if (pairs.length > 0) {
31
+ invariant(pairs.length % 2 === 0, "kwargs: needs an even number of trailing args (alternating :key value pairs)");
32
+ for (let i = 0; i < pairs.length; i += 2) {
33
+ folded[String(pairs[i]).replace(/^'?:/, "")] = toJS(pairs[i + 1] as SchemeValue);
34
+ }
35
+ }
36
+ let inputs: Record<string, unknown> | undefined;
37
+ let meta: z.infer<typeof promptMeta> | undefined;
38
+ if (positional !== undefined) {
39
+ const value = toJS(positional as SchemeValue);
40
+ if (isPlainRecord(value) && Object.keys(folded).length === 0) {
41
+ const metaRaw = isPlainRecord(value.meta) ? value.meta : {};
42
+ const { meta: _meta, key: _key, ...rest } = value;
43
+ inputs = rest;
44
+ meta = promptMeta.parse(metaRaw);
45
+ } else if (folded.evidence === undefined) {
46
+ folded.evidence = value;
47
+ }
48
+ }
49
+ if (inputs === undefined || meta === undefined) {
50
+ const metaRaw = isPlainRecord(folded.meta) ? folded.meta : {};
51
+ const { meta: _metaSlot, key: _keySlot, ...rest } = folded;
52
+ inputs = rest;
53
+ meta = promptMeta.parse(metaRaw);
54
+ }
55
+ const rendered = spec.sections.map((section): [PromptMessageRole, string] => [
56
+ section.role,
57
+ runCompiledTemplate(compileTemplate(section.source), [inputs]),
58
+ ]);
59
+ const model =
60
+ [meta.model, spec.model].find(
61
+ (candidate): candidate is string => typeof candidate === "string" && candidate !== "",
62
+ ) ?? null;
63
+ return new RenderedPrompt(
64
+ model,
65
+ meta.reasoningEffort ?? spec.reasoningEffort,
66
+ spec.responseSchema,
67
+ spec.faceName,
68
+ spec.tools,
69
+ spec.mode === "instruct" ? [["user", rendered.map(([, content]) => content).join("\n\n")]] : rendered,
70
+ );
71
+ }
72
+
73
+ /** Both prompt hosts install this prelude. Require parses once and closes over the spec. */
74
+ export const promptPrelude = `(define (ext/prompt/resolve contents)
75
+ (let ((spec (dotprompt/parse (if (bytevector? contents) (utf8->string contents) contents)
76
+ "anonymous.prompt")))
77
+ ;; apply would run dotprompt/run under the lists capability's context.
78
+ (lambda args
79
+ (dotprompt/run spec args))))
80
+ (require/register-extension ".prompt" ext/prompt/resolve)`;
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { type PromptComplete, RenderedPrompt } from "./bundle.js";
2
+ export { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
3
+ export { promptIsolatedCapability } from "./run-isolated.js";
4
+ export { promptProgramCapability } from "./run-program.js";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Isolated host for `.prompt`. `dotprompt/run` performs one completion
3
+ * on the configured job (compact, classifier).
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { arrivalLoaderCapability } from "@here.build/arrival-modules";
7
+ import { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
8
+ import { CompletionExpectation, CompletionJob, ProgrammaticJob, PromptMessage } from "@inhuman.tools/harness-model";
9
+ import { Job } from "@inhuman.tools/plexus-expectations";
10
+ import invariant from "tiny-invariant";
11
+ import { z } from "zod";
12
+
13
+ import { promptPrelude, renderPrompt } from "./dotprompt.js";
14
+
15
+ export const promptIsolatedCapability = EnvCapability.define("ext/prompt/isolated", {
16
+ deps: [dotpromptCapability, arrivalLoaderCapability],
17
+ configuration: {
18
+ job: z.instanceof(Job).refine((job) => !(job instanceof ProgrammaticJob), {
19
+ error: "dotprompt/run: a program uses promptProgramCapability",
20
+ }),
21
+ connectionId: z
22
+ .string({ error: "dotprompt/run: connectionId is required" })
23
+ .refine((value) => value !== "", { error: "dotprompt/run: connectionId is required" }),
24
+ model: z.string().optional(),
25
+ /** Session/judge model. `model` is reserved by some exec hosts. */
26
+ completionModel: z.string().optional(),
27
+ },
28
+ symbols: (symbol, sz) => ({
29
+ "dotprompt/run": symbol.rosetta`dotprompt/run: completes the rendered prompt in isolation`(
30
+ {
31
+ input: [sz.box.pipe(z.instanceof(ParsedPrompt)), sz.list(sz.dynamic)],
32
+ output: [sz.dynamic],
33
+ provenance: "source",
34
+ requiresConfig: ["job"],
35
+ },
36
+ async function (spec, args) {
37
+ const bundle = renderPrompt(spec, args);
38
+ // Render overlays :meta, then the file model. The host model is appended here.
39
+ const model =
40
+ [bundle.model, this.configuration.completionModel, this.configuration.model].find(
41
+ (candidate): candidate is string => typeof candidate === "string" && candidate !== "",
42
+ ) ?? null;
43
+ invariant(model != null, "dotprompt/run: model is required");
44
+ // The session orchestrator drives the CompletionJob. Await reads its result.
45
+ return await this.configuration.job.registerJob(
46
+ new CompletionJob({
47
+ expectation: new CompletionExpectation({
48
+ connectionId: this.configuration.connectionId,
49
+ model,
50
+ responseSchema: bundle.responseSchema,
51
+ completionMode: "isolated",
52
+ promptMessages: bundle.messages.map(([role, content]) => new PromptMessage({ role, content })),
53
+ reasoningEffort: bundle.reasoningEffort,
54
+ }),
55
+ turnTail: this.configuration.job,
56
+ }),
57
+ );
58
+ },
59
+ ),
60
+ }),
61
+ prelude: promptPrelude,
62
+ });
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Program host for `.prompt`. `dotprompt/run` parents an omitted-spec
3
+ * AgentCallJob on the ProgrammaticJob and waits for the worker.
4
+ */
5
+ import { EnvCapability } from "@here.build/arrival";
6
+ import { arrivalLoaderCapability } from "@here.build/arrival-modules";
7
+ import { dotpromptCapability, ParsedPrompt } from "@inhuman.tools/env-capability-dotprompt";
8
+ import {
9
+ AgentCallJob,
10
+ claimCrossing,
11
+ crossingPending,
12
+ crossingWindow,
13
+ isReplaying,
14
+ ProgrammaticJob,
15
+ PromptMessage,
16
+ takeCrossing,
17
+ } from "@inhuman.tools/harness-model";
18
+ import { runInAction, when } from "mobx";
19
+ import { z } from "zod";
20
+
21
+ import { promptPrelude, renderPrompt } from "./dotprompt.js";
22
+
23
+ const AGENT_ASK = "agent__ask";
24
+
25
+ export const promptProgramCapability = EnvCapability.define("ext/prompt/program", {
26
+ deps: [dotpromptCapability, arrivalLoaderCapability],
27
+ configuration: {
28
+ job: z.instanceof(ProgrammaticJob),
29
+ readonly: z.boolean().default(false),
30
+ },
31
+ symbols: (symbol, sz) => ({
32
+ "dotprompt/run": symbol.rosetta`dotprompt/run: parents an omitted-spec AgentCallJob on the program and waits`(
33
+ {
34
+ input: [sz.box.pipe(z.instanceof(ParsedPrompt)), sz.list(sz.dynamic)],
35
+ output: [sz.dynamic],
36
+ provenance: "source",
37
+ requiresConfig: ["job"],
38
+ },
39
+ async function (spec, args) {
40
+ const bundle = renderPrompt(spec, args);
41
+ const job = this.configuration.job;
42
+ const emission = this.runCtx.emission;
43
+ const path = job.trackMatch && emission != null ? claimCrossing(emission, crossingWindow(this)) : "";
44
+ if (path !== "" && emission != null) {
45
+ let existing = takeCrossing(job, emission, path);
46
+ if (existing == null && isReplaying(emission)) {
47
+ if (!job.completed && !job.cancelled) {
48
+ const joined = when(() => job.completed || job.cancelled || crossingPending(job, emission, path));
49
+ try {
50
+ await joined;
51
+ } finally {
52
+ joined.cancel();
53
+ }
54
+ }
55
+ existing = takeCrossing(job, emission, path);
56
+ if (existing == null) throw new Error("replay: no recorded dotprompt/run");
57
+ }
58
+ if (existing != null) return await existing;
59
+ }
60
+ const minted = new AgentCallJob({
61
+ toolCallId: `${job.toolCallId}:prompt:${job.children.length + 1}`,
62
+ name: AGENT_ASK,
63
+ argsJson: "{}",
64
+ voidLegal: false,
65
+ readonly: this.configuration.readonly === true,
66
+ responseSchema: bundle.responseSchema,
67
+ promptMessages: bundle.messages.map(([role, content]) => new PromptMessage({ role, content })),
68
+ faceName: bundle.faceName.trim(),
69
+ tools: bundle.tools ?? [],
70
+ inheritCallerTools: bundle.tools === null,
71
+ reasoningEffort: bundle.reasoningEffort,
72
+ });
73
+ if (path !== "") runInAction(() => (minted.track = path));
74
+ return await job.registerJob(minted);
75
+ },
76
+ ),
77
+ }),
78
+ prelude: promptPrelude,
79
+ });
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.