Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions amplifier_web/host/mentions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def __init__(self, foundation, workspace):
self.workspace = Path(workspace)

def resolve(self, mention):
return self.resolve_relative(mention, self.workspace)

def resolve_relative(self, mention, relative_to):
"""Scope local references without retargeting project/user shortcuts."""
if not mention.startswith('@') or '..' in mention:
return None
body = mention[1:]
Expand All @@ -46,8 +50,8 @@ def resolve(self, mention):
return self.foundation.resolve(mention) if self.foundation else None
else:
# Retain Foundation's plain-path and omitted-.md behavior used by
# filesystem tools, scoped to this session's workspace.
return BaseMentionResolver(base_path=self.workspace).resolve(mention)
# filesystem tools, scoped to the workspace or referring file.
return BaseMentionResolver(base_path=relative_to).resolve(mention)
if not relative:
return None
path = root / relative
Expand Down
17 changes: 17 additions & 0 deletions tests/test_runtime_mentions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ def coordinator(workspace, bundles=None):
return value


def test_per_call_relative_scope_preserves_session_shortcuts(tmp_path, monkeypatch):
workspace, nested, user, bundle = (tmp_path / name for name in ('workspace', 'nested', 'user', 'bundle'))
for path in (workspace / '.amplifier', nested, user, bundle):
path.mkdir(parents=True)
(path / 'rules.md').write_text(str(path))
monkeypatch.setenv('AMPLIFIER_HOME', str(user))
owner = coordinator(workspace, {'bundle': Bundle(name='bundle', base_path=bundle)})
resolver = owner.get_capability('mention_resolver')
assert resolver.resolve_relative('@./rules.md', nested) == nested / 'rules.md'
assert resolver.resolve_relative('@project:rules.md', nested) == workspace / '.amplifier/rules.md'
assert resolver.resolve_relative('@user:rules.md', nested) == user / 'rules.md'
assert resolver.resolve_relative('@bundle:rules.md', nested) == bundle / 'rules.md'
assert resolver.resolve_relative('@../rules.md', nested) is None
assert resolver.workspace == workspace
assert resolver.resolve('@./rules.md') is None


async def test_workspace_shortcuts_and_composed_namespace_use_shared_expander(tmp_path, monkeypatch):
workspace = tmp_path / 'workspace'
bundle = tmp_path / 'bundle'
Expand Down
Loading