Compare commits
5 Commits
686f2c7cb0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 06ccd3564e | |||
| 2977ab369e | |||
| c8998c6b0d | |||
| 81d40ae63d | |||
| 65a3fb8d2d |
@@ -328,21 +328,22 @@ function register(api: PluginAPI): void {
|
|||||||
)}\n\`\`\``;
|
)}\n\`\`\``;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First-line ack `WAKEUP_OK` is the plugin's ack-receipt token; the
|
// The wakeup dispatcher's `deliver` callback below only logs the
|
||||||
// agent MUST then continue in the same session and drive the
|
// reply text — it does NOT inspect any ack token. The earlier
|
||||||
// `hf-wakeup` workflow to completion (calendar_status → task fetch →
|
// `WAKEUP_OK` first-line-ack convention was prompt-only theatre;
|
||||||
// sub-workflow → calendar_complete/abort). Without that continuation
|
// nothing in this plugin or in openclaw acted on it. The only
|
||||||
// the scheduler keeps re-waking every 30s because the slot stays
|
// thing that ends a wake cycle is the slot transitioning out of
|
||||||
// `not_started` forever.
|
// `not_started`, which happens when the agent calls
|
||||||
|
// `harborforge_calendar_complete` or `harborforge_calendar_abort`.
|
||||||
|
// Tell the agent that plainly instead of asking for a fake ack.
|
||||||
const wakeupMessage =
|
const wakeupMessage =
|
||||||
`You have due slots. **First line of your reply MUST be exactly ` +
|
`You have due slots. Drive the \`hf-wakeup\` workflow of skill ` +
|
||||||
`\`WAKEUP_OK\`** so the plugin records the ack. Then, **in this ` +
|
`\`hf-hangman-lab\` to completion in this session — read slot ` +
|
||||||
`same session**, drive the \`hf-wakeup\` workflow of skill ` +
|
`context, call the harborforge_calendar_* tools, route to the ` +
|
||||||
`\`hf-hangman-lab\` to completion — read slot context, call the ` +
|
`right sub-workflow, and finish with harborforge_calendar_complete ` +
|
||||||
`harborforge_calendar_* tools, route to the right sub-workflow, ` +
|
`or harborforge_calendar_abort. The scheduler keeps re-waking you ` +
|
||||||
`and finish with harborforge_calendar_complete or abort. Do NOT ` +
|
`every 30s until the slot transitions out of \`not_started\`, so ` +
|
||||||
`stop after the ack — the scheduler will re-wake you every 30s ` +
|
`partial work or silence just produces another wake.${slotBlock}`;
|
||||||
`until the slot transitions out of \`not_started\`.${slotBlock}`;
|
|
||||||
|
|
||||||
const result = await dispatchInboundMessageWithDispatcher({
|
const result = await dispatchInboundMessageWithDispatcher({
|
||||||
ctx: {
|
ctx: {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const OLD_PLUGIN_NAME = 'harborforge-monitor';
|
|||||||
const PLUGIN_SRC_DIR = join(__dirname, 'plugin');
|
const PLUGIN_SRC_DIR = join(__dirname, 'plugin');
|
||||||
const SKILLS_SRC_DIR = join(__dirname, 'skills');
|
const SKILLS_SRC_DIR = join(__dirname, 'skills');
|
||||||
const MONITOR_REPO_URL = 'https://git.hangman-lab.top/zhi/HarborForge.Monitor.git';
|
const MONITOR_REPO_URL = 'https://git.hangman-lab.top/zhi/HarborForge.Monitor.git';
|
||||||
|
const CLI_REPO_URL = 'https://git.hangman-lab.top/zhi/HarborForge.Cli.git';
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const options = {
|
const options = {
|
||||||
@@ -43,6 +44,7 @@ const options = {
|
|||||||
installCli: args.includes('--install-cli'),
|
installCli: args.includes('--install-cli'),
|
||||||
installMonitor: 'no',
|
installMonitor: 'no',
|
||||||
monitorBranch: 'main',
|
monitorBranch: 'main',
|
||||||
|
cliBranch: 'main',
|
||||||
};
|
};
|
||||||
|
|
||||||
const profileIdx = args.indexOf('--openclaw-profile-path');
|
const profileIdx = args.indexOf('--openclaw-profile-path');
|
||||||
@@ -60,6 +62,11 @@ if (monitorBranchIdx !== -1 && args[monitorBranchIdx + 1]) {
|
|||||||
options.monitorBranch = String(args[monitorBranchIdx + 1]);
|
options.monitorBranch = String(args[monitorBranchIdx + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cliBranchIdx = args.indexOf('--cli-branch');
|
||||||
|
if (cliBranchIdx !== -1 && args[cliBranchIdx + 1]) {
|
||||||
|
options.cliBranch = String(args[cliBranchIdx + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
function resolveOpenclawPath() {
|
function resolveOpenclawPath() {
|
||||||
if (options.openclawProfilePath) return options.openclawProfilePath;
|
if (options.openclawProfilePath) return options.openclawProfilePath;
|
||||||
if (process.env.OPENCLAW_PATH) return resolve(process.env.OPENCLAW_PATH);
|
if (process.env.OPENCLAW_PATH) return resolve(process.env.OPENCLAW_PATH);
|
||||||
@@ -316,39 +323,40 @@ async function installCli() {
|
|||||||
if (!options.installCli) return;
|
if (!options.installCli) return;
|
||||||
const totalSteps = 6;
|
const totalSteps = 6;
|
||||||
logStep(5, totalSteps, 'Building and installing hf CLI...');
|
logStep(5, totalSteps, 'Building and installing hf CLI...');
|
||||||
|
|
||||||
const openclawPath = resolveOpenclawPath();
|
const openclawPath = resolveOpenclawPath();
|
||||||
const binDir = join(openclawPath, 'bin');
|
const binDir = join(openclawPath, 'bin');
|
||||||
mkdirSync(binDir, { recursive: true });
|
mkdirSync(binDir, { recursive: true });
|
||||||
|
|
||||||
// Find CLI source — look for HarborForge.Cli relative to project root
|
// Clone CLI repo to /tmp, build there, copy artifact out. Mirrors
|
||||||
const projectRoot = resolve(__dirname, '..');
|
// installManagedMonitor so the install never depends on a checked-out
|
||||||
const cliDir = join(projectRoot, 'HarborForge.Cli');
|
// sibling repo at a fixed path.
|
||||||
|
const tmpDir = join('/tmp', `harborforge-cli-${Date.now()}`);
|
||||||
if (!existsSync(cliDir)) {
|
const hfBinary = join(binDir, 'hf');
|
||||||
// Try parent directory (monorepo layout)
|
|
||||||
const monoCliDir = resolve(projectRoot, '..', 'HarborForge.Cli');
|
|
||||||
if (!existsSync(monoCliDir)) {
|
|
||||||
logErr(`Cannot find HarborForge.Cli at ${cliDir} or ${monoCliDir}`);
|
|
||||||
logWarn('Skipping CLI installation');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const effectiveCliDir = existsSync(cliDir)
|
|
||||||
? cliDir
|
|
||||||
: resolve(projectRoot, '..', 'HarborForge.Cli');
|
|
||||||
|
|
||||||
log(` Building hf from ${effectiveCliDir}...`, 'blue');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hfBinary = join(binDir, 'hf');
|
log(` Cloning ${CLI_REPO_URL} (branch ${options.cliBranch}) → ${tmpDir}...`, 'blue');
|
||||||
exec(`go build -o ${hfBinary} ./cmd/hf`, { cwd: effectiveCliDir, silent: !options.verbose });
|
exec(`git clone --branch ${shellEscape(options.cliBranch)} --depth 1 ${shellEscape(CLI_REPO_URL)} ${shellEscape(tmpDir)}`, { silent: !options.verbose });
|
||||||
|
|
||||||
|
// Stamp the binary with the version string the prod CLI surfaces in
|
||||||
|
// `hf version`. Fall back to a date-only label if rev-parse fails for
|
||||||
|
// any reason (shallow clone shouldn't, but be defensive).
|
||||||
|
let versionLabel = `${new Date().toISOString().slice(0, 10)}+install`;
|
||||||
|
try {
|
||||||
|
const sha = exec(`git rev-parse --short HEAD`, { cwd: tmpDir, silent: true }).trim();
|
||||||
|
if (sha) versionLabel = `${new Date().toISOString().slice(0, 10)}+${options.cliBranch}-${sha}`;
|
||||||
|
} catch { /* keep fallback */ }
|
||||||
|
|
||||||
|
log(` Building hf (version=${versionLabel})...`, 'blue');
|
||||||
|
const ldflags = `-X git.hangman-lab.top/zhi/HarborForge.Cli/internal/commands.Version=${versionLabel}`;
|
||||||
|
exec(`go build -ldflags ${shellEscape(ldflags)} -o ${shellEscape(hfBinary)} ./cmd/hf`, { cwd: tmpDir, silent: !options.verbose });
|
||||||
chmodSync(hfBinary, 0o755);
|
chmodSync(hfBinary, 0o755);
|
||||||
logOk(`hf binary → ${hfBinary}`);
|
logOk(`hf binary → ${hfBinary} (branch hint: ${options.cliBranch})`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logErr(`Failed to build hf CLI: ${err.message}`);
|
logErr(`Failed to build hf CLI: ${err.message}`);
|
||||||
logWarn('CLI installation failed, plugin still installed');
|
logWarn('CLI installation failed, plugin still installed');
|
||||||
|
} finally {
|
||||||
|
rmSync(tmpDir, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user