@atolis-hq/wake 0.2.2 → 0.2.4

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.
@@ -73,6 +73,10 @@ export const indexHtml = `<!DOCTYPE html>
73
73
  .ok { color: #7fe3a3; }
74
74
  input[type=text] { background: #1a1d23; border: 1px solid #2c313a; color: #e8e8e8; padding: 0.3rem 0.5rem; border-radius: 6px; margin-bottom: 0.6rem; width: 260px; transition: border-color 0.12s ease, box-shadow 0.12s ease; }
75
75
  input[type=text]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.15); }
76
+ a { color: var(--accent-light); text-decoration: none; }
77
+ a:hover { text-decoration: underline; }
78
+ .resource-list { list-style: none; padding: 0; margin: 0 0 1rem; }
79
+ .resource-list li { display: flex; align-items: baseline; gap: 0.4rem; margin-bottom: 0.35rem; font-size: 0.8rem; }
76
80
  </style>
77
81
  </head>
78
82
  <body>
@@ -195,6 +199,21 @@ async function renderBoard() {
195
199
  main.appendChild(columns);
196
200
  }
197
201
 
202
+ function resourceUriToUrl(resourceUri) {
203
+ const parts = resourceUri.split(':');
204
+ if (parts.length < 3) return null;
205
+ const provider = parts[0];
206
+ const type = parts[1];
207
+ const locator = parts.slice(2).join(':');
208
+ const m = locator.match(/^(.+)#([0-9]+)$/);
209
+ if (!m) return null;
210
+ if (provider === 'github') {
211
+ if (type === 'issue') return 'https://github.com/' + m[1] + '/issues/' + m[2];
212
+ if (type === 'pr') return 'https://github.com/' + m[1] + '/pull/' + m[2];
213
+ }
214
+ return null;
215
+ }
216
+
198
217
  async function openItem(repo, number) {
199
218
  const drawer = document.getElementById('drawer');
200
219
  const body = document.getElementById('drawer-body');
@@ -203,12 +222,27 @@ async function openItem(repo, number) {
203
222
  const detail = await getJson('/items/' + encodeURIComponent(repo) + '/' + number);
204
223
  if (!detail) { body.textContent = 'Not found'; return; }
205
224
  body.innerHTML = '';
206
- body.appendChild(el('h2', { text: repo + '#' + number }));
225
+ const headLink = el('a', { href: detail.item.issue.url, target: '_blank', rel: 'noopener noreferrer', text: repo + '#' + number });
226
+ body.appendChild(el('h2', {}, [headLink]));
207
227
  body.appendChild(el('p', { text: detail.item.issue.title }));
208
228
  body.appendChild(el('p', { class: 'meta', text: 'stage: ' + detail.item.wake.stage + (detail.item.wake.sessionId ? ' · session: ' + detail.item.wake.sessionId : '') }));
209
229
  if (detail.item.wake.workspacePath) {
210
230
  body.appendChild(el('p', { class: 'meta', text: 'workspace: ' + detail.item.wake.workspacePath }));
211
231
  }
232
+ const resources = detail.item.correlatedResources || [];
233
+ if (resources.length > 0) {
234
+ body.appendChild(el('h3', { text: 'Resources' }));
235
+ const resourceList = el('ul', { class: 'resource-list' });
236
+ for (const res of resources) {
237
+ const resUrl = resourceUriToUrl(res.resourceUri);
238
+ const badge = el('span', { class: 'chip', text: res.role });
239
+ const linkOrText = resUrl
240
+ ? el('a', { href: resUrl, target: '_blank', rel: 'noopener noreferrer', text: res.resourceUri })
241
+ : el('span', { class: 'meta', text: res.resourceUri });
242
+ resourceList.appendChild(el('li', {}, [badge, linkOrText]));
243
+ }
244
+ body.appendChild(resourceList);
245
+ }
212
246
  body.appendChild(el('h3', { text: 'Runs' }));
213
247
  const runsTable = el('table', {}, [
214
248
  el('tr', {}, ['action', 'status', 'sentinel', 'started', 'runId'].map((h) => el('th', { text: h }))),
@@ -4,7 +4,10 @@ import { createDefaultWakeConfig } from '../config/defaults.js';
4
4
  import { splitWakeConfig } from '../config/split-config.js';
5
5
  import { writeYamlFile } from '../lib/yaml-file.js';
6
6
  import { createWakePaths } from '../lib/paths.js';
7
- const promptFileNames = ['refine.md', 'implement.md'];
7
+ async function listPromptFileNames(repoRoot) {
8
+ const entries = await readdir(join(repoRoot, 'prompts'));
9
+ return entries.filter((name) => name.endsWith('.md')).sort();
10
+ }
8
11
  function sanitizeContainerName(name) {
9
12
  const sanitized = name
10
13
  .toLowerCase()
@@ -87,6 +90,7 @@ export async function scaffoldWakeHome(input) {
87
90
  ];
88
91
  await Promise.all(runtimeDirectories.map((directoryPath) => mkdir(directoryPath, { recursive: true })));
89
92
  const { infra, workflow } = splitWakeConfig(config);
93
+ const promptFileNames = await listPromptFileNames(repoRoot);
90
94
  await Promise.all([
91
95
  copyAssets(repoRoot, 'prompts', join(wakeRoot, 'prompts'), promptFileNames),
92
96
  writeYamlFile(join(wakeRoot, 'config.yaml'), infra),
@@ -5,7 +5,6 @@ export function createDefaultWakeConfig(wakeRoot = resolve(process.cwd(), '.wake
5
5
  return parseWakeConfig({
6
6
  paths: {
7
7
  wakeRoot,
8
- promptsRoot: resolve(wakeRoot, 'prompts'),
9
8
  },
10
9
  });
11
10
  }
@@ -1,5 +1,6 @@
1
1
  import { resolve, join } from 'node:path';
2
2
  import { access } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
3
4
  import { readJsonFile } from '../lib/json-file.js';
4
5
  import { readYamlFile } from '../lib/yaml-file.js';
5
6
  import { deepMergeRaw } from '../lib/deep-merge.js';
@@ -44,13 +45,24 @@ export async function loadWakeConfig(options) {
44
45
  }
45
46
  // wakeRoot is always the live invocation's --wake-root/cwd, never a value
46
47
  // to accept from a (possibly stale, possibly container-context) config
47
- // file — spread rawPaths first so wakeRoot always wins. promptsRoot and
48
- // any other paths key stay file-overridable.
48
+ // file — spread rawPaths first so wakeRoot always wins. promptsRoot stays
49
+ // file-overridable for a genuine custom location, but when the file is
50
+ // silent on it we default to the live wakeRoot's own prompts/ dir (the
51
+ // usual colocated layout `wake init` scaffolds) rather than leaving it to
52
+ // fall back to bundled prompts — this keeps a scaffolded home's prompt
53
+ // customizations in effect across host/container re-reads of the same
54
+ // config file, where an absolute promptsRoot baked in at init time would
55
+ // not resolve the same way.
49
56
  const rawPaths = raw.paths ?? {};
57
+ const wakeRootPromptsDir = join(wakeRoot, 'prompts');
58
+ const promptsRootDefault = rawPaths.promptsRoot === undefined && existsSync(wakeRootPromptsDir)
59
+ ? { promptsRoot: wakeRootPromptsDir }
60
+ : {};
50
61
  return parseWakeConfig({
51
62
  ...raw,
52
63
  paths: {
53
64
  ...rawPaths,
65
+ ...promptsRootDefault,
54
66
  wakeRoot,
55
67
  },
56
68
  });
@@ -1 +1 @@
1
- export const wakeVersion = "0.2.2+g83e9f9a";
1
+ export const wakeVersion = "0.2.4+g59df9f2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {