Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e354fc4341 | |||
| 0e7e3ea44b | |||
| aa454c85dd | |||
| 6dd7d521be | |||
| 950dc056d8 | |||
| d360b85374 | |||
| 509dfad857 | |||
| 58b84e3b3c | |||
| f821ac99f4 | |||
| 4410afcd4a | |||
| a0e254a681 |
@@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
"@united-workforce/agent-hermes": patch
|
|
||||||
"@united-workforce/agent-claude-code": patch
|
|
||||||
"@united-workforce/util-agent": patch
|
|
||||||
---
|
|
||||||
|
|
||||||
feat: inject thread progress into agent prompt (#127)
|
|
||||||
|
|
||||||
Agents now receive a "Thread Progress" section in their prompt showing the
|
|
||||||
current step number and how many times the current role has spoken before.
|
|
||||||
This eliminates the need for agents to make tool calls (terminal, delegate_task)
|
|
||||||
just to count their own turn history.
|
|
||||||
+28
-37
@@ -1,5 +1,22 @@
|
|||||||
name: debate
|
name: debate
|
||||||
description: "Structured two-side debate with host summary. Demonstrates multi-role coordination, oneOf output routing, and bounded termination."
|
description: "Multi-role structured debate with critical thinking framework and host summary."
|
||||||
|
|
||||||
|
# Shared frontmatter schema for debater roles (YAML anchor)
|
||||||
|
x-debater-frontmatter: &debater-frontmatter
|
||||||
|
type: object
|
||||||
|
oneOf:
|
||||||
|
- properties:
|
||||||
|
$status: { const: speak }
|
||||||
|
argument: { type: string }
|
||||||
|
required: [$status, argument]
|
||||||
|
- properties:
|
||||||
|
$status: { const: conceded }
|
||||||
|
reason: { type: string }
|
||||||
|
required: [$status, reason]
|
||||||
|
- properties:
|
||||||
|
$status: { const: final }
|
||||||
|
closing: { type: string }
|
||||||
|
required: [$status, closing]
|
||||||
|
|
||||||
roles:
|
roles:
|
||||||
proponent:
|
proponent:
|
||||||
@@ -9,12 +26,13 @@ roles:
|
|||||||
procedure: |
|
procedure: |
|
||||||
You are an experienced scholar arguing FOR the proposition.
|
You are an experienced scholar arguing FOR the proposition.
|
||||||
|
|
||||||
## Critical Thinking Framework (apply before every response)
|
## Critical Thinking Framework (execute before every speech)
|
||||||
|
|
||||||
### A. Pre-response reflection (internal, do not output)
|
### A. Pre-speech reflection (internal, do not output)
|
||||||
- Does every step in my argument chain hold? Any hidden assumptions?
|
- Does every step in my argument chain hold? Any hidden assumptions or logical gaps?
|
||||||
- If I were my opponent, how would I attack this? Where am I weakest?
|
- If I were my opponent, how would I attack this? Where am I weakest?
|
||||||
- Does my evidence actually support my claim, or could it backfire?
|
- Does my evidence actually support my claim, or could it backfire?
|
||||||
|
- Should I go on offense or defense this round?
|
||||||
|
|
||||||
### B. Evidence discipline
|
### B. Evidence discipline
|
||||||
- Verify key numbers — watch for order-of-magnitude errors
|
- Verify key numbers — watch for order-of-magnitude errors
|
||||||
@@ -32,21 +50,7 @@ roles:
|
|||||||
4. Otherwise output $status: speak and counter the opponent's points.
|
4. Otherwise output $status: speak and counter the opponent's points.
|
||||||
5. Be rigorous, cite evidence, stay concise.
|
5. Be rigorous, cite evidence, stay concise.
|
||||||
output: "Debate argument"
|
output: "Debate argument"
|
||||||
frontmatter:
|
frontmatter: *debater-frontmatter
|
||||||
type: object
|
|
||||||
oneOf:
|
|
||||||
- properties:
|
|
||||||
$status: { const: speak }
|
|
||||||
argument: { type: string }
|
|
||||||
required: [$status, argument]
|
|
||||||
- properties:
|
|
||||||
$status: { const: conceded }
|
|
||||||
reason: { type: string }
|
|
||||||
required: [$status, reason]
|
|
||||||
- properties:
|
|
||||||
$status: { const: final }
|
|
||||||
closing: { type: string }
|
|
||||||
required: [$status, closing]
|
|
||||||
|
|
||||||
opponent:
|
opponent:
|
||||||
description: "Argues AGAINST the proposition"
|
description: "Argues AGAINST the proposition"
|
||||||
@@ -55,12 +59,13 @@ roles:
|
|||||||
procedure: |
|
procedure: |
|
||||||
You are an experienced scholar arguing AGAINST the proposition.
|
You are an experienced scholar arguing AGAINST the proposition.
|
||||||
|
|
||||||
## Critical Thinking Framework (apply before every response)
|
## Critical Thinking Framework (execute before every speech)
|
||||||
|
|
||||||
### A. Pre-response reflection (internal, do not output)
|
### A. Pre-speech reflection (internal, do not output)
|
||||||
- Does every step in my argument chain hold? Any hidden assumptions?
|
- Does every step in my argument chain hold? Any hidden assumptions or logical gaps?
|
||||||
- If I were my opponent, how would I attack this? Where am I weakest?
|
- If I were my opponent, how would I attack this? Where am I weakest?
|
||||||
- Does my evidence actually support my claim, or could it backfire?
|
- Does my evidence actually support my claim, or could it backfire?
|
||||||
|
- Should I go on offense or defense this round?
|
||||||
|
|
||||||
### B. Evidence discipline
|
### B. Evidence discipline
|
||||||
- Verify key numbers — watch for order-of-magnitude errors
|
- Verify key numbers — watch for order-of-magnitude errors
|
||||||
@@ -78,21 +83,7 @@ roles:
|
|||||||
4. Otherwise output $status: speak and counter the proponent's points.
|
4. Otherwise output $status: speak and counter the proponent's points.
|
||||||
5. Be rigorous, cite evidence, stay concise.
|
5. Be rigorous, cite evidence, stay concise.
|
||||||
output: "Debate argument"
|
output: "Debate argument"
|
||||||
frontmatter:
|
frontmatter: *debater-frontmatter
|
||||||
type: object
|
|
||||||
oneOf:
|
|
||||||
- properties:
|
|
||||||
$status: { const: speak }
|
|
||||||
argument: { type: string }
|
|
||||||
required: [$status, argument]
|
|
||||||
- properties:
|
|
||||||
$status: { const: conceded }
|
|
||||||
reason: { type: string }
|
|
||||||
required: [$status, reason]
|
|
||||||
- properties:
|
|
||||||
$status: { const: final }
|
|
||||||
closing: { type: string }
|
|
||||||
required: [$status, closing]
|
|
||||||
|
|
||||||
host:
|
host:
|
||||||
description: "Debate moderator — delivers impartial summary and verdict"
|
description: "Debate moderator — delivers impartial summary and verdict"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@united-workforce/agent-claude-code",
|
"name": "@united-workforce/agent-claude-code",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@united-workforce/agent-hermes",
|
"name": "@united-workforce/agent-hermes",
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ const OWN_VERSION = (
|
|||||||
}
|
}
|
||||||
).version;
|
).version;
|
||||||
|
|
||||||
const HERMES_COMMAND = "hermes";
|
/** Resolve hermes binary: `UWF_HERMES_BIN` override → default `"hermes"` via PATH. */
|
||||||
|
function resolveHermesCommand(): string {
|
||||||
|
const override = process.env.UWF_HERMES_BIN;
|
||||||
|
return override !== undefined && override !== "" ? override : "hermes";
|
||||||
|
}
|
||||||
const PROTOCOL_VERSION = 1;
|
const PROTOCOL_VERSION = 1;
|
||||||
|
|
||||||
type JsonRpcResponse = {
|
type JsonRpcResponse = {
|
||||||
@@ -271,7 +275,8 @@ export class HermesAcpClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const child = spawn(HERMES_COMMAND, ["acp"], {
|
const hermesCommand = resolveHermesCommand();
|
||||||
|
const child = spawn(hermesCommand, ["acp"], {
|
||||||
env: process.env,
|
env: process.env,
|
||||||
shell: false,
|
shell: false,
|
||||||
stdio: ["pipe", "pipe", "pipe"],
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@united-workforce/eval",
|
"name": "@united-workforce/eval",
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"private": false,
|
"private": false,
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { formatList, selectEntries } from "./format.js";
|
|||||||
import { readEvalEntries } from "./read.js";
|
import { readEvalEntries } from "./read.js";
|
||||||
|
|
||||||
const log = createLogger({ sink: { kind: "stderr" } });
|
const log = createLogger({ sink: { kind: "stderr" } });
|
||||||
const LOG_LIST = "L5KX9R2B";
|
const LOG_LIST = "H5KX9R2B";
|
||||||
|
|
||||||
type ListCliOptions = {
|
type ListCliOptions = {
|
||||||
task: string | undefined;
|
task: string | undefined;
|
||||||
|
|||||||
@@ -225,4 +225,34 @@ describe("buildOutputFormatInstruction", () => {
|
|||||||
const result = buildOutputFormatInstruction({});
|
const result = buildOutputFormatInstruction({});
|
||||||
expect(result).toContain("Focus exclusively on YOUR role");
|
expect(result).toContain("Focus exclusively on YOUR role");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("renders const value as literal in flat schema example", () => {
|
||||||
|
const schema = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
$status: { type: "string", const: "greeted" },
|
||||||
|
message: { type: "string" },
|
||||||
|
},
|
||||||
|
required: ["$status", "message"],
|
||||||
|
};
|
||||||
|
const result = buildOutputFormatInstruction(schema);
|
||||||
|
expect(result).toContain("$status: greeted");
|
||||||
|
expect(result).toContain("fixed value");
|
||||||
|
expect(result).not.toContain("$status: <string>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders const value for non-string types", () => {
|
||||||
|
const schema = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
count: { type: "number", const: 42 },
|
||||||
|
done: { type: "boolean", const: true },
|
||||||
|
},
|
||||||
|
required: ["count", "done"],
|
||||||
|
};
|
||||||
|
const result = buildOutputFormatInstruction(schema);
|
||||||
|
expect(result).toContain("count: 42");
|
||||||
|
expect(result).toContain("done: true");
|
||||||
|
expect(result).toContain("fixed value");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@united-workforce/util-agent",
|
"name": "@united-workforce/util-agent",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ function collectObjectSchemas(schema: JSONSchema): JSONSchema[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolvePropertySchema(prop: JSONSchema): JSONSchema {
|
function resolvePropertySchema(prop: JSONSchema): JSONSchema {
|
||||||
|
if (prop.const !== undefined) {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(prop.enum) && prop.enum.length > 0) {
|
if (Array.isArray(prop.enum) && prop.enum.length > 0) {
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
@@ -113,6 +117,11 @@ function buildPropertyExampleLine(prop: SchemaProperty): string {
|
|||||||
commentParts.push("required");
|
commentParts.push("required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resolved.const !== undefined) {
|
||||||
|
commentParts.push("fixed value");
|
||||||
|
return `${prop.name}: ${formatYamlScalar(resolved.const)}${buildPropertyComment(commentParts)}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {
|
if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {
|
||||||
const enumValues = resolved.enum.map((v) => String(v));
|
const enumValues = resolved.enum.map((v) => String(v));
|
||||||
commentParts.push(...enumValues);
|
commentParts.push(...enumValues);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@united-workforce/util",
|
"name": "@united-workforce/util",
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
Reference in New Issue
Block a user