@ghl-ai/aw 0.1.73-beta.0 → 0.1.73-beta.2
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/commands/init.mjs +0 -6
- package/constants.mjs +1 -1
- package/ecc.mjs +1 -1
- package/hooks/aw-usage/hooks/aw-usage-commit-created.js +13 -4
- package/hooks/aw-usage/hooks/aw-usage-prompt-submit.js +3 -1
- package/hooks/aw-usage/hooks/aw-usage-telemetry-send.js +1 -1
- package/hooks/aw-usage/lib/aw-usage-telemetry.js +85 -1
- package/hooks.mjs +2 -2
- package/package.json +3 -3
package/commands/init.mjs
CHANGED
|
@@ -25,7 +25,6 @@ import * as fmt from '../fmt.mjs';
|
|
|
25
25
|
import { chalk, setSilent } from '../fmt.mjs';
|
|
26
26
|
import { linkWorkspace } from '../link.mjs';
|
|
27
27
|
import { generateCommands, copyInstructions, initAwDocs, syncHomeHarnessInstructions } from '../integrate.mjs';
|
|
28
|
-
import { renderRules } from '../render-rules.mjs';
|
|
29
28
|
import { setupMcp } from '../mcp.mjs';
|
|
30
29
|
import { isContextModeRequested } from '../integrations/context-mode.mjs';
|
|
31
30
|
import { applyStoredStartupPreferences, ensureAwRuntimeHook, isDefaultRoutingEnabled } from '../startup.mjs';
|
|
@@ -151,11 +150,6 @@ function syncHomeAndProjectInstructions(cwd, namespace) {
|
|
|
151
150
|
initAwDocs(HOME);
|
|
152
151
|
if (cwd !== HOME) {
|
|
153
152
|
syncInstructionsAndAwDocs(cwd, namespace);
|
|
154
|
-
} else {
|
|
155
|
-
// Running from $HOME (fresh-laptop flow): render global IDE rules directly.
|
|
156
|
-
// The project branch above is otherwise the only renderRules call site, so
|
|
157
|
-
// init from $HOME used to leave ~/.claude/rules and ~/.cursor/rules empty.
|
|
158
|
-
renderRules(HOME, { homeDir: HOME });
|
|
159
153
|
}
|
|
160
154
|
}
|
|
161
155
|
|
package/constants.mjs
CHANGED
|
@@ -105,7 +105,7 @@ export const RULES_SOURCE_DIR = '.aw_rules';
|
|
|
105
105
|
/** Runtime location exposed to harnesses and generated instructions */
|
|
106
106
|
export const RULES_RUNTIME_DIR = '.aw/.aw_rules';
|
|
107
107
|
/** Telemetry endpoint — override with AW_TELEMETRY_URL env var */
|
|
108
|
-
export const TELEMETRY_URL = process.env.AW_TELEMETRY_URL || 'https://services.leadconnectorhq.com/agentic-workspace/api/telemetry/events';
|
|
108
|
+
export const TELEMETRY_URL = process.env.AW_TELEMETRY_URL || 'https://staging.services.leadconnectorhq.com/agentic-workspace/api/telemetry/events';
|
|
109
109
|
|
|
110
110
|
/** AW bot identity for Co-Authored-By trailers */
|
|
111
111
|
export const AW_BOT_NAME = 'AW';
|
package/ecc.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { applyStoredStartupPreferences } from "./startup.mjs";
|
|
|
12
12
|
|
|
13
13
|
const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
|
|
14
14
|
const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
|
|
15
|
-
export const AW_ECC_TAG = "v1.4.
|
|
15
|
+
export const AW_ECC_TAG = "v1.4.67";
|
|
16
16
|
const REQUIRED_ECC_FILES = [
|
|
17
17
|
"package.json",
|
|
18
18
|
"scripts/install-apply.js",
|
|
@@ -11,14 +11,23 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
buildEvent,
|
|
16
|
+
sendAsync,
|
|
17
|
+
isDisabled,
|
|
18
|
+
findRecentSdlcSessionForProject,
|
|
19
|
+
} = require('../lib/aw-usage-telemetry');
|
|
15
20
|
|
|
16
21
|
function buildCommitCreatedEvent({ commitHash = 'unknown', branch = 'unknown', cwd = process.cwd() } = {}) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
const linkedSession = findRecentSdlcSessionForProject(cwd);
|
|
23
|
+
const event = buildEvent({
|
|
24
|
+
cwd,
|
|
25
|
+
...(linkedSession?.session_id ? { session_id: linkedSession.session_id } : {}),
|
|
26
|
+
}, 'commit_created', {
|
|
20
27
|
commit_hash: commitHash,
|
|
28
|
+
commit_sha: commitHash,
|
|
21
29
|
branch,
|
|
30
|
+
...(linkedSession?.session_id ? { linked_session_source: 'project_recent_sdlc_session' } : {}),
|
|
22
31
|
});
|
|
23
32
|
|
|
24
33
|
// Override harness to 'git' since this fires from a git hook, not a harness.
|
|
@@ -109,7 +109,9 @@ function processPromptSubmitInput(input, deps = {}) {
|
|
|
109
109
|
|
|
110
110
|
if (slash) {
|
|
111
111
|
persistSkill(getSessionId(input), input?.turn_id || null, slash);
|
|
112
|
-
persistSlashCmd(getSessionId(input), slash
|
|
112
|
+
persistSlashCmd(getSessionId(input), slash, {
|
|
113
|
+
cwd: input?.cwd || (input?.workspace_roots && input.workspace_roots[0]) || null,
|
|
114
|
+
});
|
|
113
115
|
events.push({
|
|
114
116
|
eventType: 'skill_invoked',
|
|
115
117
|
payload: {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const https = require('https');
|
|
13
13
|
const http = require('http');
|
|
14
14
|
|
|
15
|
-
const DEFAULT_URL = 'https://services.leadconnectorhq.com/agentic-workspace/api/telemetry/usage-events';
|
|
15
|
+
const DEFAULT_URL = 'https://staging.services.leadconnectorhq.com/agentic-workspace/api/telemetry/usage-events';
|
|
16
16
|
const TIMEOUT_MS = 10_000;
|
|
17
17
|
|
|
18
18
|
function post(url, body) {
|
|
@@ -21,6 +21,7 @@ const SENDER_SCRIPT = path.join(__dirname, '..', 'hooks', 'aw-usage-telemetry-se
|
|
|
21
21
|
const AW_HOME = path.join(os.homedir(), '.aw');
|
|
22
22
|
const CONFIG_PATH = path.join(AW_HOME, 'telemetry', 'config.json');
|
|
23
23
|
const SESSION_DIR = path.join(AW_HOME, 'telemetry', 'sessions');
|
|
24
|
+
const SESSION_PROJECT_DIR = path.join(SESSION_DIR, 'by-project');
|
|
24
25
|
const DEDUPE_DIR = path.join(os.tmpdir(), 'aw-usage-telemetry-dedupe');
|
|
25
26
|
|
|
26
27
|
// ── Git config cache (once per process) ──────────────────────────────
|
|
@@ -157,6 +158,16 @@ function computeProjectHash(cwd) {
|
|
|
157
158
|
return crypto.createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
158
159
|
}
|
|
159
160
|
|
|
161
|
+
function normalizeProjectHash(value) {
|
|
162
|
+
return typeof value === 'string' && /^[a-f0-9]{16}$/i.test(value) ? value.toLowerCase() : null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function resolveProjectHash(context) {
|
|
166
|
+
if (!context || typeof context !== 'object') return null;
|
|
167
|
+
return normalizeProjectHash(context.project_hash || context.projectHash)
|
|
168
|
+
|| computeProjectHash(context.cwd);
|
|
169
|
+
}
|
|
170
|
+
|
|
160
171
|
// ── Session file cleanup ─────────────────────────────────────────────
|
|
161
172
|
// Prune session files older than SESSION_MAX_AGE_MS to prevent unbounded growth.
|
|
162
173
|
// Called once per session start — best-effort, never blocks.
|
|
@@ -241,21 +252,40 @@ function readSessionSkill(sessionId, turnId) {
|
|
|
241
252
|
// to the originating /aw:* invocation. Separate from `last_skill` because
|
|
242
253
|
// the source is the prompt, not the tool, and the lifetime is the whole
|
|
243
254
|
// session (not just one turn).
|
|
244
|
-
function
|
|
255
|
+
function writeProjectSessionIndex(projectHash, sessionId, slashCommand) {
|
|
256
|
+
if (!projectHash || !sessionId || !slashCommand?.is_sdlc_stage) return;
|
|
257
|
+
try {
|
|
258
|
+
fs.mkdirSync(SESSION_PROJECT_DIR, { recursive: true });
|
|
259
|
+
fs.writeFileSync(path.join(SESSION_PROJECT_DIR, `${projectHash}.json`), JSON.stringify({
|
|
260
|
+
project_hash: projectHash,
|
|
261
|
+
session_id: sessionId,
|
|
262
|
+
command_namespace: slashCommand.command_namespace || null,
|
|
263
|
+
command_name: slashCommand.command_name,
|
|
264
|
+
is_sdlc_stage: Boolean(slashCommand.is_sdlc_stage),
|
|
265
|
+
updated_at: new Date().toISOString(),
|
|
266
|
+
}));
|
|
267
|
+
} catch { /* ignore */ }
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function persistSessionSlashCommand(sessionId, slashCommand, context = {}) {
|
|
245
271
|
if (!sessionId || !slashCommand?.command_name) return;
|
|
246
272
|
try {
|
|
247
273
|
fs.mkdirSync(SESSION_DIR, { recursive: true });
|
|
248
274
|
const state = readSessionState(sessionId);
|
|
275
|
+
const projectHash = resolveProjectHash(context) || state.project_hash || null;
|
|
249
276
|
fs.writeFileSync(path.join(SESSION_DIR, sessionId + '.json'), JSON.stringify({
|
|
250
277
|
...state,
|
|
278
|
+
...(projectHash ? { project_hash: projectHash } : {}),
|
|
251
279
|
last_slash_command: {
|
|
252
280
|
command_namespace: slashCommand.command_namespace || null,
|
|
253
281
|
command_name: slashCommand.command_name,
|
|
254
282
|
command_args: slashCommand.command_args || '',
|
|
255
283
|
is_sdlc_stage: Boolean(slashCommand.is_sdlc_stage),
|
|
284
|
+
...(projectHash ? { project_hash: projectHash } : {}),
|
|
256
285
|
updated_at: new Date().toISOString(),
|
|
257
286
|
},
|
|
258
287
|
}));
|
|
288
|
+
writeProjectSessionIndex(projectHash, sessionId, slashCommand);
|
|
259
289
|
} catch { /* ignore */ }
|
|
260
290
|
}
|
|
261
291
|
|
|
@@ -265,6 +295,59 @@ function readSessionLastSlashCommand(sessionId) {
|
|
|
265
295
|
return cmd;
|
|
266
296
|
}
|
|
267
297
|
|
|
298
|
+
function parseUpdatedAt(value) {
|
|
299
|
+
const millis = Date.parse(value || '');
|
|
300
|
+
return Number.isFinite(millis) ? millis : 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function isRecentSdlcSessionCandidate(candidate, projectHash, maxAgeMs) {
|
|
304
|
+
if (!candidate?.session_id) return false;
|
|
305
|
+
if (!candidate?.is_sdlc_stage) return false;
|
|
306
|
+
if (candidate.project_hash !== projectHash) return false;
|
|
307
|
+
const updatedAt = parseUpdatedAt(candidate.updated_at);
|
|
308
|
+
if (!updatedAt) return false;
|
|
309
|
+
return Date.now() - updatedAt <= maxAgeMs;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function readProjectSessionIndex(projectHash, maxAgeMs) {
|
|
313
|
+
try {
|
|
314
|
+
const candidate = JSON.parse(fs.readFileSync(path.join(SESSION_PROJECT_DIR, `${projectHash}.json`), 'utf8'));
|
|
315
|
+
return isRecentSdlcSessionCandidate(candidate, projectHash, maxAgeMs) ? candidate : null;
|
|
316
|
+
} catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function findRecentSdlcSessionForProject(cwd, maxAgeMs = SESSION_MAX_AGE_MS) {
|
|
322
|
+
const projectHash = computeProjectHash(cwd);
|
|
323
|
+
if (!projectHash) return null;
|
|
324
|
+
|
|
325
|
+
const indexed = readProjectSessionIndex(projectHash, maxAgeMs);
|
|
326
|
+
if (indexed) return indexed;
|
|
327
|
+
|
|
328
|
+
let best = null;
|
|
329
|
+
try {
|
|
330
|
+
const entries = fs.readdirSync(SESSION_DIR);
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (!entry.endsWith('.json')) continue;
|
|
333
|
+
const sessionId = entry.slice(0, -'.json'.length);
|
|
334
|
+
const state = readSessionState(sessionId);
|
|
335
|
+
const cmd = state.last_slash_command;
|
|
336
|
+
const candidate = {
|
|
337
|
+
session_id: sessionId,
|
|
338
|
+
project_hash: cmd?.project_hash || state.project_hash || null,
|
|
339
|
+
is_sdlc_stage: Boolean(cmd?.is_sdlc_stage),
|
|
340
|
+
updated_at: cmd?.updated_at || state.updated_at || null,
|
|
341
|
+
};
|
|
342
|
+
if (!isRecentSdlcSessionCandidate(candidate, projectHash, maxAgeMs)) continue;
|
|
343
|
+
if (!best || parseUpdatedAt(candidate.updated_at) > parseUpdatedAt(best.updated_at)) {
|
|
344
|
+
best = candidate;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
} catch { /* ignore */ }
|
|
348
|
+
return best;
|
|
349
|
+
}
|
|
350
|
+
|
|
268
351
|
// ── Short-TTL dedupe guards ──────────────────────────────────────────
|
|
269
352
|
|
|
270
353
|
function normalizeDedupePart(value) {
|
|
@@ -503,6 +586,7 @@ module.exports = {
|
|
|
503
586
|
readSessionSkill,
|
|
504
587
|
persistSessionSlashCommand,
|
|
505
588
|
readSessionLastSlashCommand,
|
|
589
|
+
findRecentSdlcSessionForProject,
|
|
506
590
|
readLastAssistantFromTranscript,
|
|
507
591
|
resolvePromptText,
|
|
508
592
|
getAwCliVersionDetails,
|
package/hooks.mjs
CHANGED
|
@@ -102,7 +102,7 @@ if git log -1 --format='%b' HEAD 2>/dev/null | grep -qF "Co-Authored-By: AW"; th
|
|
|
102
102
|
TELEMETRY_HOOK="$HOME/.aw-ecc/scripts/hooks/aw-usage-commit-created.js"
|
|
103
103
|
fi
|
|
104
104
|
if command -v node >/dev/null 2>&1 && [ -f "$TELEMETRY_HOOK" ]; then
|
|
105
|
-
COMMIT_HASH="$(git rev-parse
|
|
105
|
+
COMMIT_HASH="$(git rev-parse HEAD 2>/dev/null || echo unknown)"
|
|
106
106
|
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)"
|
|
107
107
|
node "$TELEMETRY_HOOK" "$COMMIT_HASH" "$BRANCH" "$(pwd)" >/dev/null 2>&1
|
|
108
108
|
fi
|
|
@@ -286,7 +286,7 @@ if git log -1 --format='%b' HEAD 2>/dev/null | grep -qF "Co-Authored-By: AW"; th
|
|
|
286
286
|
TELEMETRY_HOOK="$HOME/.aw-ecc/scripts/hooks/aw-usage-commit-created.js"
|
|
287
287
|
fi
|
|
288
288
|
if command -v node >/dev/null 2>&1 && [ -f "$TELEMETRY_HOOK" ]; then
|
|
289
|
-
COMMIT_HASH="$(git rev-parse
|
|
289
|
+
COMMIT_HASH="$(git rev-parse HEAD 2>/dev/null || echo unknown)"
|
|
290
290
|
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)"
|
|
291
291
|
node "$TELEMETRY_HOOK" "$COMMIT_HASH" "$BRANCH" "$(pwd)" >/dev/null 2>&1
|
|
292
292
|
fi
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghl-ai/aw",
|
|
3
|
-
"version": "0.1.73-beta.
|
|
4
|
-
"description": "Agentic Workspace CLI
|
|
3
|
+
"version": "0.1.73-beta.2",
|
|
4
|
+
"description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"aw": "bin.js"
|
|
@@ -74,4 +74,4 @@
|
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"vitest": "^4.1.2"
|
|
76
76
|
}
|
|
77
|
-
}
|
|
77
|
+
}
|